mirror of https://github.com/usememos/memos
feat: implement sign in with SSO (#1119)
* feat: implement sign in with SSO * chore: update * chore: update * chore: updatepull/1120/head
parent
708049bb89
commit
d0b8b076cf
@ -0,0 +1,74 @@
|
|||||||
|
import { last } from "lodash-es";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useSearchParams } from "react-router-dom";
|
||||||
|
import * as api from "../helpers/api";
|
||||||
|
import toastHelper from "../components/Toast";
|
||||||
|
import { absolutifyLink } from "../helpers/utils";
|
||||||
|
import { useUserStore } from "../store/module";
|
||||||
|
import Icon from "../components/Icon";
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
loading: boolean;
|
||||||
|
errorMessage: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AuthCallback = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const [state, setState] = useState<State>({
|
||||||
|
loading: true,
|
||||||
|
errorMessage: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const code = searchParams.get("code");
|
||||||
|
const state = searchParams.get("state");
|
||||||
|
|
||||||
|
if (code && state) {
|
||||||
|
const redirectUri = absolutifyLink("/auth/callback");
|
||||||
|
const identityProviderId = Number(last(state.split("-")));
|
||||||
|
if (identityProviderId) {
|
||||||
|
api
|
||||||
|
.signinWithSSO(identityProviderId, code, redirectUri)
|
||||||
|
.then(async () => {
|
||||||
|
setState({
|
||||||
|
loading: false,
|
||||||
|
errorMessage: "",
|
||||||
|
});
|
||||||
|
const user = await userStore.doSignIn();
|
||||||
|
if (user) {
|
||||||
|
window.location.href = "/";
|
||||||
|
} else {
|
||||||
|
toastHelper.error(t("message.login-failed"));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error(error);
|
||||||
|
setState({
|
||||||
|
loading: false,
|
||||||
|
errorMessage: JSON.stringify(error.response.data, null, 2),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setState({
|
||||||
|
loading: false,
|
||||||
|
errorMessage: "Failed to authorize. Invalid state passed to the auth callback.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-4 w-full h-full flex justify-center items-center">
|
||||||
|
{state.loading ? (
|
||||||
|
<Icon.Loader className="animate-spin dark:text-gray-200" />
|
||||||
|
) : (
|
||||||
|
<div className="max-w-lg font-mono whitespace-pre-wrap opacity-80">{state.errorMessage}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AuthCallback;
|
Loading…
Reference in New Issue