fix: invalid jwt assertion error handling (#11933)

# Which Problems Are Solved

Incorrectly mapped errors on the `/oauth/v2/token` endpoint lead to a
large number of HTTP status 500 errors.

# How the Problems Are Solved

By mapping invalid jwt assertion errors to OIDC `invalid_client` errors,
which returns a HTTP status 400.

# Additional Changes

N/A

# Additional Context

- Closes https://github.com/zitadel/zitadel/issues/11924
- Follow-up: 
- Fix the [error
handling](https://github.com/zitadel/oidc/blob/main/pkg/oidc/verifier.go#L195)
in the oidc package

---------

Co-authored-by: Copilot <[email protected]>
This commit is contained in:
Gayathri Vijayan
2026-04-01 10:44:02 +02:00
committed by GitHub
co-authored by Copilot
parent 330548e13c
commit 5344a7f584
2 changed files with 25 additions and 10 deletions
@@ -26,6 +26,10 @@ func TestServer_JWTProfile(t *testing.T) {
_, _, keyDataExpired, err := Instance.CreateOIDCJWTProfileClient(CTX, 10*time.Second)
require.NoError(t, err)
project := Instance.CreateProject(CTX, t, "", integration.ProjectName(), false, false)
_, appKeyData, err := Instance.CreateOIDCWebClientJWT(CTX, redirectURI, logoutRedirectURI, project.GetId())
require.NoError(t, err)
type claims struct {
name string
username string
@@ -36,11 +40,12 @@ func TestServer_JWTProfile(t *testing.T) {
orgDomain any
}
tests := []struct {
name string
keyData []byte
scope []string
wantClaims claims
wantErr bool
name string
keyData []byte
scope []string
wantClaims claims
wantErr bool
expectedErr error
}{
{
name: "success",
@@ -107,10 +112,18 @@ func TestServer_JWTProfile(t *testing.T) {
},
},
{
name: "key expired",
keyData: keyDataExpired,
scope: []string{oidc.ScopeOpenID},
wantErr: true,
name: "key expired",
keyData: keyDataExpired,
scope: []string{oidc.ScopeOpenID},
wantErr: true,
expectedErr: oidc.ErrInvalidGrant().WithDescription("invalid assertion"),
},
{
name: "key type application",
keyData: appKeyData,
scope: []string{oidc.ScopeOpenID},
wantErr: true,
expectedErr: oidc.ErrInvalidGrant().WithDescription("invalid assertion"),
},
}
for _, tt := range tests {
@@ -132,6 +145,7 @@ func TestServer_JWTProfile(t *testing.T) {
time.Minute, time.Second,
)
if tt.wantErr {
assert.ErrorIs(t, err, tt.expectedErr)
return
}
+2 -1
View File
@@ -8,6 +8,7 @@ import (
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/query"
@@ -76,7 +77,7 @@ func (s *Server) verifyJWTProfile(ctx context.Context, req *oidc.JWTProfileGrant
)
_, err = op.VerifyJWTAssertion(ctx, req.Assertion, verifier)
if err != nil {
return nil, err
return nil, oidc.ErrInvalidGrant().WithParent(err).WithReturnParentToClient(authz.GetFeatures(ctx).DebugOIDCParentError).WithDescription("invalid assertion")
}
return storage.user, nil
}