mirror of
https://github.com/zitadel/zitadel.git
synced 2025-04-15 18:11:29 +00:00
fix(oidc): only return state
in access token response for implicit flow (#8108)
# Which Problems Are Solved Introduced with #7822 the access token response incorrectly returned the `state` parameter. # How the Problems Are Solved The `state` will only be returned for access token responses in an implicit_flow. # Additional Changes None. # Additional Context - relates to #7822 - relates to https://github.com/zitadel/oidc/issues/446#issuecomment-2144999644 - backport to 2.53.x --------- Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
This commit is contained in:
parent
f4d32d98d3
commit
fb95f4a8a2
@ -528,6 +528,9 @@ func assertTokens(t *testing.T, tokens *oidc.Tokens[*oidc.IDTokenClaims], requir
|
|||||||
} else {
|
} else {
|
||||||
assert.Empty(t, tokens.RefreshToken)
|
assert.Empty(t, tokens.RefreshToken)
|
||||||
}
|
}
|
||||||
|
// since we test implicit flow directly, we can check that any token response must not
|
||||||
|
// return a `state` in the response
|
||||||
|
assert.Empty(t, tokens.Extra("state"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertIDTokenClaims(t *testing.T, claims *oidc.IDTokenClaims, userID string, arm []string, sessionStart, sessionChange time.Time, sessionID string) {
|
func assertIDTokenClaims(t *testing.T, claims *oidc.IDTokenClaims, userID string, arm []string, sessionStart, sessionChange time.Time, sessionID string) {
|
||||||
|
@ -34,41 +34,40 @@ func (s *Server) CodeExchange(ctx context.Context, r *op.ClientRequest[oidc.Acce
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
session *command.OIDCSession
|
session *command.OIDCSession
|
||||||
state string
|
|
||||||
)
|
)
|
||||||
if strings.HasPrefix(plainCode, command.IDPrefixV2) {
|
if strings.HasPrefix(plainCode, command.IDPrefixV2) {
|
||||||
session, state, err = s.command.CreateOIDCSessionFromAuthRequest(
|
session, _, err = s.command.CreateOIDCSessionFromAuthRequest(
|
||||||
setContextUserSystem(ctx),
|
setContextUserSystem(ctx),
|
||||||
plainCode,
|
plainCode,
|
||||||
codeExchangeComplianceChecker(client, r.Data),
|
codeExchangeComplianceChecker(client, r.Data),
|
||||||
slices.Contains(client.GrantTypes(), oidc.GrantTypeRefreshToken),
|
slices.Contains(client.GrantTypes(), oidc.GrantTypeRefreshToken),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
session, state, err = s.codeExchangeV1(ctx, client, r.Data, r.Data.Code)
|
session, err = s.codeExchangeV1(ctx, client, r.Data, r.Data.Code)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return response(s.accessTokenResponseFromSession(ctx, client, session, state, client.client.ProjectID, client.client.ProjectRoleAssertion, client.client.AccessTokenRoleAssertion, client.client.IDTokenRoleAssertion, client.client.IDTokenUserinfoAssertion))
|
return response(s.accessTokenResponseFromSession(ctx, client, session, "", client.client.ProjectID, client.client.ProjectRoleAssertion, client.client.AccessTokenRoleAssertion, client.client.IDTokenRoleAssertion, client.client.IDTokenUserinfoAssertion))
|
||||||
}
|
}
|
||||||
|
|
||||||
// codeExchangeV1 creates a v2 token from a v1 auth request.
|
// codeExchangeV1 creates a v2 token from a v1 auth request.
|
||||||
func (s *Server) codeExchangeV1(ctx context.Context, client *Client, req *oidc.AccessTokenRequest, code string) (session *command.OIDCSession, state string, err error) {
|
func (s *Server) codeExchangeV1(ctx context.Context, client *Client, req *oidc.AccessTokenRequest, code string) (session *command.OIDCSession, err error) {
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
authReq, err := s.getAuthRequestV1ByCode(ctx, code)
|
authReq, err := s.getAuthRequestV1ByCode(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if challenge := authReq.GetCodeChallenge(); challenge != nil || client.AuthMethod() == oidc.AuthMethodNone {
|
if challenge := authReq.GetCodeChallenge(); challenge != nil || client.AuthMethod() == oidc.AuthMethodNone {
|
||||||
if err = op.AuthorizeCodeChallenge(req.CodeVerifier, challenge); err != nil {
|
if err = op.AuthorizeCodeChallenge(req.CodeVerifier, challenge); err != nil {
|
||||||
return nil, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if req.RedirectURI != authReq.GetRedirectURI() {
|
if req.RedirectURI != authReq.GetRedirectURI() {
|
||||||
return nil, "", oidc.ErrInvalidGrant().WithDescription("redirect_uri does not correspond")
|
return nil, oidc.ErrInvalidGrant().WithDescription("redirect_uri does not correspond")
|
||||||
}
|
}
|
||||||
|
|
||||||
scope := authReq.GetScopes()
|
scope := authReq.GetScopes()
|
||||||
@ -88,9 +87,9 @@ func (s *Server) codeExchangeV1(ctx context.Context, client *Client, req *oidc.A
|
|||||||
slices.Contains(scope, oidc.ScopeOfflineAccess),
|
slices.Contains(scope, oidc.ScopeOfflineAccess),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
return session, authReq.TransferState, s.repo.DeleteAuthRequest(ctx, authReq.ID)
|
return session, s.repo.DeleteAuthRequest(ctx, authReq.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAuthRequestV1ByCode finds the v1 auth request by code.
|
// getAuthRequestV1ByCode finds the v1 auth request by code.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user