我想将 OIDC 添加到我的 React 应用程序中,并且我正在使用oidc-客户端-ts https://stackblitz.com/github/remix-run/react-router/tree/main/examples/auth?file=src%2FApp.tsx因为它似乎很受欢迎并且仍在维护中。我的问题是我错过了一些 React 示例。
我想要的是除了一条路线之外的所有路线都受到保护。如果用户未经过身份验证,则应将他们重定向到登录屏幕,其中有一个按钮可使用自定义提供程序激活身份验证流程。
我尝试过使用these https://stackblitz.com/github/remix-run/react-router/tree/main/examples/auth?file=src%2FApp.tsx two https://github.com/authts/sample-angular-oidc-client-ts示例,但我不确定如何将它们粘合在一起以及如何将 Angular 代码转换为 React。
到目前为止,我已将整个应用程序包装在 AuthContext 中,并将除一条路由之外的所有路由设为私有,如第一个例子 https://stackblitz.com/github/remix-run/react-router/tree/main/examples/auth?file=src%2FApp.tsx:
索引.tsx:
<StrictMode>
<AuthProvider>
<BrowserRouter>
<Routes>
<Route path={routes.LOGIN} element={<LoginContainer />} />
<Route element={<Layout />}>
<Route index element={<Home />} />
<Route path="/openid/callback" element={<AuthCallback />} />
// Other pages
</Route>
<Route path="*" element={<ErrorPage />} />
</Routes>
</BrowserRouter>
</AuthProvider>
</StrictMode>
The Layout
- 具有私有路由的组件,以创建所有路径,但"/login"
私人的:
function RequireAuth({ children }: { children: JSX.Element }) {
const auth = useAuth();
if (!auth.user) {
return <Navigate to="/login" replace />;
}
return children;
}
function Layout() {
return (
<RequireAuth>
<>
<Header />
<Main />
<Footer />
</>
</RequireAuth>
);
}
授权提供者:
const AuthContext = createContext<AuthContextType>(null!);
const useAuth = () => useContext(AuthContext);
function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<any>(null);
const authService = new AuthService();
const login = () => authService.login().then(user1 => setUser(user1));
const loginCallback = async () => {
const authedUser = await authService.loginCallback();
setUser(authedUser);
};
const logout = () => authService.login().then(() => setUser(null));
const value = { user, login, logout };
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
export { AuthProvider, useAuth };
The authService
刚刚复制自角度示例 https://github.com/authts/sample-angular-oidc-client-ts/blob/main/src/app/core/services/auth.service.ts:
import { User, UserManager } from "oidc-client-ts";
export default class AuthService {
userManager: UserManager;
constructor() {
const settings = {
authority: "...",
client_id: "...",
redirect_uri: "http://localhost:3000/openid/callback",
client_secret: "...",
post_logout_redirect_uri: "http://localhost:3000/login"
};
this.userManager = new UserManager(settings);
}
public getUser(): Promise<User | null> {
return this.userManager.getUser();
}
public login(): Promise<void> {
return this.userManager.signinRedirect();
}
public loginCallback(): Promise<User> {
return this.userManager.signinRedirectCallback();
}
public logout(): Promise<void> {
return this.userManager.signoutRedirect();
}
}
我的问题是我不知道如何在中设置用户AuthProvider
这样我就可以检查我是否已在RequireAuth
-成分。我的里面没有设置then
in the AuthProvider
s 登录和注销功能,所以每当我尝试登录时,我都会被重定向到登录页面。
有人可以告诉我如何使用 OIDC 进行身份验证流程并限制所有路径,但仅允许经过身份验证的用户访问吗?
此外这个答案 https://stackoverflow.com/a/59370777/7925759说应该有一个AuthorizationCallback
- 解析 URL 的组件。当我使用oidc-客户端-ts https://stackblitz.com/github/remix-run/react-router/tree/main/examples/auth?file=src%2FApp.tsx这似乎为我解析数据,我真的需要这个额外的步骤还是我可以将重定向 URL 设为“/”或“/home”?
Edit:
我发现signinRedirect
转到新的 URL,这意味着脚本的其余部分永远不会运行。signinRedirectCallback
是返回用户的调用。当我弄清楚如何正确保护路线时,我会将其作为答案发布。办理入住手续RequireAuth
在设置用户之前完成。如何推迟检查,直到设置用户,这样即使我已登录也不会重定向到登录?如果我刷新页面,我就会丢失user
状态来自AuthProvider
即使有活动会话,我也会被发送到登录页面。当我以干净的方式加载应用程序时,我不确定在哪里以及如何检查是否有会话正在运行。