From 7cc22b6b6a71ae6d1d9ca7e0146fb136a0057a91 Mon Sep 17 00:00:00 2001 From: youdie006 Date: Tue, 18 Aug 2026 09:59:26 +0900 Subject: [PATCH] fix(oidc): map ErrSubjectInvalid to invalid_grant instead of server_error A JWT-profile (RFC 7523) grant where iss != sub is rejected with ErrSubjectInvalid. DefaultToServerError did not list ErrSubjectInvalid in its invalid_grant case, so it fell through to default and was returned as server_error (HTTP 500) instead of invalid_grant (HTTP 400) - a spurious 500 for a merely-invalid request, logged at error level. Its sibling ErrSubjectMissing was already mapped to invalid_grant; ErrSubjectInvalid being absent was an oversight. The fix only corrects the error code of an already-rejected request and weakens no security check. Closes #945 --- pkg/oidc/error.go | 1 + pkg/oidc/error_test.go | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/pkg/oidc/error.go b/pkg/oidc/error.go index e9f7327e..78ec0963 100644 --- a/pkg/oidc/error.go +++ b/pkg/oidc/error.go @@ -222,6 +222,7 @@ func DefaultToServerError(err error, description string) *Error { oidcErr = ErrInvalidRequest().WithParent(err).WithDescription("%s", description) case errors.Is(err, ErrIssuerInvalid), errors.Is(err, ErrSubjectMissing), + errors.Is(err, ErrSubjectInvalid), errors.Is(err, ErrAudience), errors.Is(err, ErrAzpMissing), errors.Is(err, ErrAzpInvalid), diff --git a/pkg/oidc/error_test.go b/pkg/oidc/error_test.go index b8f05077..1d546052 100644 --- a/pkg/oidc/error_test.go +++ b/pkg/oidc/error_test.go @@ -99,6 +99,16 @@ func TestDefaultToServerError(t *testing.T) { } } +// TestDefaultToServerError_SubjectInvalid guards against a regression where +// ErrSubjectInvalid (returned by the JWT profile grant when iss != sub) was not +// listed in the invalid_grant case and fell through to server_error (HTTP 500). +// A rejected client assertion must map to invalid_grant per RFC 7523, matching +// the sibling ErrSubjectMissing. +func TestDefaultToServerError_SubjectInvalid(t *testing.T) { + got := DefaultToServerError(ErrSubjectInvalid, ErrSubjectInvalid.Error()) + assert.Equal(t, InvalidGrant, got.ErrorType) +} + func TestError_LogLevel(t *testing.T) { tests := []struct { name string