From b75fe9ac1e65c202443a70f20cb55b75b163079f Mon Sep 17 00:00:00 2001 From: Stavros Date: Fri, 12 Jun 2026 12:43:18 +0300 Subject: [PATCH] fix: fix bugs in jwt parsing and redirect uri handling --- frontend/src/lib/hooks/redirect-uri.ts | 2 +- frontend/src/pages/authorize-page.tsx | 6 +----- frontend/src/pages/error-page.tsx | 2 +- frontend/src/pages/login-page.tsx | 4 +++- internal/service/oidc_service.go | 28 ++++++++++++++++++-------- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/frontend/src/lib/hooks/redirect-uri.ts b/frontend/src/lib/hooks/redirect-uri.ts index aeeae0c5..38e8b5c5 100644 --- a/frontend/src/lib/hooks/redirect-uri.ts +++ b/frontend/src/lib/hooks/redirect-uri.ts @@ -15,7 +15,7 @@ export const useRedirectUri = ( let isAllowedProto = false; let isHttpsDowngrade = false; - if (redirect_uri === undefined) { + if (!redirect_uri) { return { valid: isValid, trusted: isTrusted, diff --git a/frontend/src/pages/authorize-page.tsx b/frontend/src/pages/authorize-page.tsx index 3251c774..ae355be0 100644 --- a/frontend/src/pages/authorize-page.tsx +++ b/frontend/src/pages/authorize-page.tsx @@ -110,11 +110,7 @@ export const AuthorizePage = () => { }, }); - if ( - !isOidc || - screenParams.oidc_ticket === undefined || - screenParams.oidc_scope === undefined - ) { + if (!isOidc || !screenParams.oidc_ticket || !screenParams.oidc_scope) { return ( { const { t } = useTranslation(); const { search } = useLocation(); const searchParams = new URLSearchParams(search); - const error = searchParams.get("error") ?? ""; + const error = searchParams.get("error") || ""; return ( diff --git a/frontend/src/pages/login-page.tsx b/frontend/src/pages/login-page.tsx index e6cb2a60..5851b19c 100644 --- a/frontend/src/pages/login-page.tsx +++ b/frontend/src/pages/login-page.tsx @@ -168,7 +168,8 @@ export const LoginPage = () => { !auth.authenticated && isOauthAutoRedirect && !hasAutoRedirectedRef.current && - screenParams.login_for !== undefined + screenParams.redirect_uri && + screenParams.login_for ) { hasAutoRedirectedRef.current = true; oauthMutate(oauth.autoRedirect); @@ -180,6 +181,7 @@ export const LoginPage = () => { oauth.autoRedirect, isOauthAutoRedirect, screenParams.login_for, + screenParams.redirect_uri, ]); useEffect(() => { diff --git a/internal/service/oidc_service.go b/internal/service/oidc_service.go index cafb59d1..3fec6f48 100644 --- a/internal/service/oidc_service.go +++ b/internal/service/oidc_service.go @@ -107,7 +107,6 @@ type TokenResponse struct { } type AuthorizeRequest struct { - jwt.Claims Scope string `form:"scope" json:"scope" url:"scope"` ResponseType string `form:"response_type" json:"response_type" url:"response_type"` ClientID string `form:"client_id" json:"client_id" url:"client_id"` @@ -888,19 +887,32 @@ func (service *OIDCService) DeleteAuthorizeRequestTicket(ticket string) { // TODO: support signed request objects in the future func (service *OIDCService) DecodeAuthorizeJWT(tokenString string) (*AuthorizeRequest, error) { - var req AuthorizeRequest - - token, _, err := jwt.NewParser().ParseUnverified(tokenString, &req) + var claims jwt.MapClaims + token, _, err := jwt.NewParser().ParseUnverified(tokenString, &claims) if err != nil { return nil, fmt.Errorf("failed to parse authorize request jwt: %w", err) } - claims, ok := token.Claims.(*AuthorizeRequest) + alg, ok := token.Header["alg"].(string) - if !ok { - return nil, errors.New("failed to parse claims from authorize request jwt") + if !ok || alg != "none" || string(token.Signature) != "" { + return nil, fmt.Errorf("only unsigned jwts are supported for authorize requests") } - return claims, nil + get := func(k string) string { + v, _ := claims[k].(string) + return v + } + + return &AuthorizeRequest{ + Scope: get("scope"), + ResponseType: get("response_type"), + ClientID: get("client_id"), + RedirectURI: get("redirect_uri"), + State: get("state"), + Nonce: get("nonce"), + CodeChallenge: get("code_challenge"), + CodeChallengeMethod: get("code_challenge_method"), + }, nil }