auth: add OAuth error handling in TokenVerifier and tests (#399)

Add ErrOAuth error type and handling to match TypeScript SDK behavior.
OAuth protocol errors now return HTTP 400 instead of 500, providing
better error classification for authentication issues.

Changes

- Add ErrOAuth variable for OAuth-specific protocol errors
- Update verify function to return 400 for OAuth errors
- Add test case for OAuth error handling


Fixes compatibility with TypeScript SDK error handling patterns.
This commit is contained in:
Shusaku Yasoda 2025-09-04 02:05:07 +09:00 • committed by GitHub
commit 1250a31b51
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 12 additions and 1 deletions

View file

@ -24,6 +24,9 @@ type TokenInfo struct {
// The error that a TokenVerifier should return if the token cannot be verified. // The error that a TokenVerifier should return if the token cannot be verified.
var ErrInvalidToken = errors.New("invalid token") var ErrInvalidToken = errors.New("invalid token")
// The error that a TokenVerifier should return for OAuth-specific protocol errors.
var ErrOAuth = errors.New("oauth error")
// A TokenVerifier checks the validity of a bearer token, and extracts information // A TokenVerifier checks the validity of a bearer token, and extracts information
// from it. If verification fails, it should return an error that unwraps to ErrInvalidToken. // from it. If verification fails, it should return an error that unwraps to ErrInvalidToken.
type TokenVerifier func(ctx context.Context, token string) (*TokenInfo, error) type TokenVerifier func(ctx context.Context, token string) (*TokenInfo, error)
@ -88,7 +91,9 @@ func verify(ctx context.Context, verifier TokenVerifier, opts *RequireBearerToke
if errors.Is(err, ErrInvalidToken) { if errors.Is(err, ErrInvalidToken) {
return nil, err.Error(), http.StatusUnauthorized return nil, err.Error(), http.StatusUnauthorized
} }
// TODO: the TS SDK distinguishes another error, OAuthError, and returns a 400. if errors.Is(err, ErrOAuth) {
return nil, err.Error(), http.StatusBadRequest
}
// Investigate how that works. // Investigate how that works.
// See typescript-sdk/src/server/auth/middleware/bearerAuth.ts. // See typescript-sdk/src/server/auth/middleware/bearerAuth.ts.
return nil, err.Error(), http.StatusInternalServerError return nil, err.Error(), http.StatusInternalServerError

View file

@ -19,6 +19,8 @@ func TestVerify(t *testing.T) {
return &TokenInfo{Expiration: time.Now().Add(time.Hour)}, nil return &TokenInfo{Expiration: time.Now().Add(time.Hour)}, nil
case "invalid": case "invalid":
return nil, ErrInvalidToken return nil, ErrInvalidToken
case "oauth":
return nil, ErrOAuth
case "noexp": case "noexp":
return &TokenInfo{}, nil return &TokenInfo{}, nil
case "expired": case "expired":
@ -47,6 +49,10 @@ func TestVerify(t *testing.T) {
"invalid", nil, "bearer invalid", "invalid", nil, "bearer invalid",
"invalid token", 401, "invalid token", 401,
}, },
{
"oauth error", nil, "Bearer oauth",
"oauth error", 400,
},
{ {
"no expiration", nil, "Bearer noexp", "no expiration", nil, "Bearer noexp",
"token missing expiration", 401, "token missing expiration", 401,