fix(frontend): validate oidc state in callback flow
This commit is contained in:
@@ -32,8 +32,10 @@ const error = ref('')
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const code = route.query.code
|
||||
const state = route.query.state
|
||||
const oauthError = route.query.error
|
||||
const oauthErrorDesc = route.query.error_description
|
||||
const expectedState = sessionStorage.getItem('oidc_expected_state')
|
||||
|
||||
if (oauthError) {
|
||||
const reason = typeof oauthErrorDesc === 'string' && oauthErrorDesc
|
||||
@@ -50,6 +52,13 @@ onMounted(async () => {
|
||||
return
|
||||
}
|
||||
|
||||
if (!state || !expectedState || state !== expectedState) {
|
||||
sessionStorage.removeItem('oidc_expected_state')
|
||||
error.value = '登入驗證失敗,請重新登入'
|
||||
setTimeout(() => router.push('/login'), 3000)
|
||||
return
|
||||
}
|
||||
|
||||
const redirectUri = `${window.location.origin}/auth/callback`
|
||||
const res = await exchangeOidcCode(code, redirectUri)
|
||||
const { access_token } = res.data
|
||||
@@ -65,10 +74,12 @@ onMounted(async () => {
|
||||
await authStore.fetchMe()
|
||||
|
||||
// 導向原頁面或預設的 /me
|
||||
sessionStorage.removeItem('oidc_expected_state')
|
||||
const redirect = sessionStorage.getItem('post_login_redirect') || '/me'
|
||||
sessionStorage.removeItem('post_login_redirect')
|
||||
router.push(redirect)
|
||||
} catch (err) {
|
||||
sessionStorage.removeItem('oidc_expected_state')
|
||||
const detail = err.response?.data?.detail
|
||||
if (detail === 'invalid_authorization_code') {
|
||||
error.value = '授權代碼無效,請重新登入'
|
||||
|
||||
@@ -51,7 +51,13 @@ async function handleOidcLogin() {
|
||||
sessionStorage.setItem('post_login_redirect', typeof redirect === 'string' ? redirect : '/me')
|
||||
const callbackUrl = `${window.location.origin}/auth/callback`
|
||||
const res = await getOidcAuthorizeUrl(callbackUrl)
|
||||
window.location.href = res.data.authorize_url
|
||||
const authorizeUrl = res.data.authorize_url
|
||||
const parsed = new URL(authorizeUrl)
|
||||
const state = parsed.searchParams.get('state')
|
||||
if (state) {
|
||||
sessionStorage.setItem('oidc_expected_state', state)
|
||||
}
|
||||
window.location.href = authorizeUrl
|
||||
} catch (err) {
|
||||
const detail = err.response?.data?.detail
|
||||
if (detail === 'authentik_login_not_configured') {
|
||||
|
||||
Reference in New Issue
Block a user