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