oidc-client-js 总是重定向到登录页面
oidc-client-js always redirect to login page
我正在做一个项目,在 React SPA 上设置 OIDC 身份验证(带有 PKCE 的授权码)。
我正在使用 oidc-client-js 库。
我的代码工作正常,但在通过身份验证后,我再次被重定向到登录模式。
我查看了 React 路由器端,但似乎并非如此。我在想一个异步问题,但我似乎无法摆脱它。你能帮帮我吗?
提前致谢
我的配置
const userManager = new UserManager({
authority: identityProvider,
client_id: window.REACT_APP_CLIENT_ID,
response_type: 'code',
redirect_uri: 'http://localhost:3000/auth-callback',
scope: 'openid',
loadUserInfo: false,
revokeAccessTokenOnSignout: true,
filterProtocolClaims: true,
monitorSession: true,
metadata: {
issuer: identityProvider,
jwks_uri: `${identityProvider}/pf/JWKS`,
end_session_endpoint: `${identityProvider}/idp/startSLO.ping`,
authorization_endpoint: `${identityProvider}/as/authorization.oauth2`,
token_endpoint: `${identityProvider}/as/token.oauth2`,
userinfo_endpoint: `${identityProvider}/idp/userinfo.openid`,
revocation_endpoint: `${identityProvider}/as/revoke_token.oauth2`,
introspection_endpoint: `${identityProvider}/as/introspect.oauth2`
}
})
我的 AuthProvider
import React, { useEffect, useState } from 'react'
import PropTypes from 'prop-types'
import IdentityProvider from './bo-authentication/context/IdentityProvider'
import useCompleteAuthentication from './useCompleteAuthentication'
import useStartAuthentication from './useStartAuthentication'
const AuthProvider = ({ children }) => {
const [ready, setReady] = useState(false)
useStartAuthentication()
const boAuthentication = useCompleteAuthentication()
console.log(boAuthentication)
useEffect(() => {
setReady(boAuthentication.token !== undefined)
}, [boAuthentication.token])
if (!ready) return null
return <IdentityProvider value={boAuthentication}>{children}</IdentityProvider>
}
AuthProvider.propTypes = { children: PropTypes.node }
export default AuthProvider
我的服务
export const login = async () => {
await userManager
.signinRedirect({ redirectUri: window.location.href })
.then(() => {
console.log(`User login successful`)
})
.catch((error) => console.error(`An error occur during user login flow ${error}`))
}
export const completeAuthentication = once(
async (updater: UserAuthenticationUpdater = () => undefined): Promise<void> => {
await userManager
.signinRedirectCallback()
.then((user: User | null) => {
if (!user?.access_token) {
console.warn('The identity provider have not provide the access token')
} else {
const userAuthentication = getUserAuthentication(user)
updater(userAuthentication)
const millisecondsBeforeExpiration = getMillisecondsBeforeExpiration(
userAuthentication.exp as number
)
console.log(`The time before refresh token is ${millisecondsBeforeExpiration}`)
}
})
.catch(() => console.error('An error occur during the handle callback from the identity provider'))
}
)
挂钩
import { useContext, useEffect, useState } from 'react'
import { completeAuthentication } from '..'
import AuthenticationContext from '../context/AuthenticationContext'
import { UserAuthentication } from '../model/userAuthentication'
const useBoAuthentication = (): UserAuthentication => {
const authenticationContextValue = useContext(AuthenticationContext)
const [authenticationContext, setAuthenticationContext] = useState<UserAuthentication>(authenticationContextValue)
useEffect(() => {
if (authenticationContextValue.authenticated) return
completeAuthentication(setAuthenticationContext)
}, [authenticationContextValue.authenticated])
return authenticationContext
}
导出默认 useBoAuthentication
挂钩
import { useContext, useEffect } from 'react'
import AuthenticationContext from '../context/AuthenticationContext'
import { login } from '../index'
const useStartAuthentication = () => {
const authenticationContextValue = useContext(AuthenticationContext)
useEffect(() => {
if (authenticationContextValue.authenticated) return
login()
}, [authenticationContextValue.authenticated])
}
export default useStartAuthentication
您需要根据是否 userManager.getUser returns 对调用 signInRedirect 的时间进行更严格的控制。我将从这种方法开始:
- 当页面加载时,将登录状态呈现为屏幕上的标签:true 或 false
- 使用临时登录按钮触发登录重定向,而不是在 useEffect 中自动执行
一旦可靠,您就可以放回 onLoad 自动重定向。如果有帮助,这里是 some code of mine 对比 - 您也可以 运行 这个代码示例非常容易。
当我在 userManager 实例中检查用户时它起作用了。我认为我在 hooks 级别对 authenticated 的验证就足够了。
非常感谢您的效率和反应。
我正在做一个项目,在 React SPA 上设置 OIDC 身份验证(带有 PKCE 的授权码)。 我正在使用 oidc-client-js 库。 我的代码工作正常,但在通过身份验证后,我再次被重定向到登录模式。 我查看了 React 路由器端,但似乎并非如此。我在想一个异步问题,但我似乎无法摆脱它。你能帮帮我吗?
提前致谢
我的配置
const userManager = new UserManager({
authority: identityProvider,
client_id: window.REACT_APP_CLIENT_ID,
response_type: 'code',
redirect_uri: 'http://localhost:3000/auth-callback',
scope: 'openid',
loadUserInfo: false,
revokeAccessTokenOnSignout: true,
filterProtocolClaims: true,
monitorSession: true,
metadata: {
issuer: identityProvider,
jwks_uri: `${identityProvider}/pf/JWKS`,
end_session_endpoint: `${identityProvider}/idp/startSLO.ping`,
authorization_endpoint: `${identityProvider}/as/authorization.oauth2`,
token_endpoint: `${identityProvider}/as/token.oauth2`,
userinfo_endpoint: `${identityProvider}/idp/userinfo.openid`,
revocation_endpoint: `${identityProvider}/as/revoke_token.oauth2`,
introspection_endpoint: `${identityProvider}/as/introspect.oauth2`
}
})
我的 AuthProvider
import React, { useEffect, useState } from 'react'
import PropTypes from 'prop-types'
import IdentityProvider from './bo-authentication/context/IdentityProvider'
import useCompleteAuthentication from './useCompleteAuthentication'
import useStartAuthentication from './useStartAuthentication'
const AuthProvider = ({ children }) => {
const [ready, setReady] = useState(false)
useStartAuthentication()
const boAuthentication = useCompleteAuthentication()
console.log(boAuthentication)
useEffect(() => {
setReady(boAuthentication.token !== undefined)
}, [boAuthentication.token])
if (!ready) return null
return <IdentityProvider value={boAuthentication}>{children}</IdentityProvider>
}
AuthProvider.propTypes = { children: PropTypes.node }
export default AuthProvider
我的服务
export const login = async () => {
await userManager
.signinRedirect({ redirectUri: window.location.href })
.then(() => {
console.log(`User login successful`)
})
.catch((error) => console.error(`An error occur during user login flow ${error}`))
}
export const completeAuthentication = once(
async (updater: UserAuthenticationUpdater = () => undefined): Promise<void> => {
await userManager
.signinRedirectCallback()
.then((user: User | null) => {
if (!user?.access_token) {
console.warn('The identity provider have not provide the access token')
} else {
const userAuthentication = getUserAuthentication(user)
updater(userAuthentication)
const millisecondsBeforeExpiration = getMillisecondsBeforeExpiration(
userAuthentication.exp as number
)
console.log(`The time before refresh token is ${millisecondsBeforeExpiration}`)
}
})
.catch(() => console.error('An error occur during the handle callback from the identity provider'))
}
)
挂钩
import { useContext, useEffect, useState } from 'react'
import { completeAuthentication } from '..'
import AuthenticationContext from '../context/AuthenticationContext'
import { UserAuthentication } from '../model/userAuthentication'
const useBoAuthentication = (): UserAuthentication => {
const authenticationContextValue = useContext(AuthenticationContext)
const [authenticationContext, setAuthenticationContext] = useState<UserAuthentication>(authenticationContextValue)
useEffect(() => {
if (authenticationContextValue.authenticated) return
completeAuthentication(setAuthenticationContext)
}, [authenticationContextValue.authenticated])
return authenticationContext
}
导出默认 useBoAuthentication
挂钩
import { useContext, useEffect } from 'react'
import AuthenticationContext from '../context/AuthenticationContext'
import { login } from '../index'
const useStartAuthentication = () => {
const authenticationContextValue = useContext(AuthenticationContext)
useEffect(() => {
if (authenticationContextValue.authenticated) return
login()
}, [authenticationContextValue.authenticated])
}
export default useStartAuthentication
您需要根据是否 userManager.getUser returns 对调用 signInRedirect 的时间进行更严格的控制。我将从这种方法开始:
- 当页面加载时,将登录状态呈现为屏幕上的标签:true 或 false
- 使用临时登录按钮触发登录重定向,而不是在 useEffect 中自动执行
一旦可靠,您就可以放回 onLoad 自动重定向。如果有帮助,这里是 some code of mine 对比 - 您也可以 运行 这个代码示例非常容易。
当我在 userManager 实例中检查用户时它起作用了。我认为我在 hooks 级别对 authenticated 的验证就足够了。
非常感谢您的效率和反应。