ory/hydra · error
Session must be of type JWTSessionContainer but got type: %T
Error message
Session must be of type JWTSessionContainer but got type: %T
What it means
fosite's DefaultJWTStrategy.generate requires the requester's session to implement JWTSessionContainer; any other Session implementation cannot contribute JWT claims and is rejected with this type assertion error. It is a programming/configuration error: the session type attached to the request is wrong for JWT token generation.
Source
Thrown at fosite/handler/oauth2/strategy_jwt.go:90
case v.Has(jwt.ValidationErrorUnverifiable | jwt.ValidationErrorSignatureInvalid):
return fosite.ErrTokenSignatureMismatch
case v.Has(jwt.ValidationErrorExpired):
return fosite.ErrTokenExpired
case v.Has(jwt.ValidationErrorAudience |
jwt.ValidationErrorIssuedAt |
jwt.ValidationErrorIssuer |
jwt.ValidationErrorNotValidYet |
jwt.ValidationErrorId |
jwt.ValidationErrorClaimsInvalid):
return fosite.ErrTokenClaim
default:
return fosite.ErrRequestUnauthorized
}
}
func (h *DefaultJWTStrategy) generate(ctx context.Context, tokenType fosite.TokenType, requester fosite.Requester) (string, string, error) {
if jwtSession, ok := requester.GetSession().(JWTSessionContainer); !ok {
return "", "", errors.Errorf("Session must be of type JWTSessionContainer but got type: %T", requester.GetSession())
} else if claims := jwtSession.GetJWTClaims(); claims == nil {
return "", "", errors.New("GetTokenClaims() must not be nil")
} else {
claims.
With(
jwtSession.GetExpiresAt(tokenType),
requester.GetGrantedScopes(),
requester.GetGrantedAudience(),
).
WithDefaults(
time.Now().UTC(),
h.Config.GetAccessTokenIssuer(ctx),
).
WithScopeField(
h.Config.GetJWTScopeField(ctx),
)
return h.Signer.Generate(ctx, claims.ToMapClaims(), jwtSession.GetJWTHeader())View on GitHub (pinned to 4174065ffb)
Solutions
- Use/attach a session type implementing JWTSessionContainer (e.g. compose fosite's JWTSession or implement GetJWTClaims/GetExpiresAt/GetSubject) for JWT strategy requests
- Ensure the session manager/storage creates the JWT-capable session type for token requests, not the default session
- If you need opaque tokens, configure the hmac strategy instead of jwt for that grant type
- Add a startup type check: if _, ok := sess.(fositeJWT.JWTSessionContainer); !ok { fail fast }
Example fix
// before
session := &fosite.DefaultSession{Subject: user.ID}
// after
session := &oauth2.JWTSession{Session: &fosite.DefaultSession{Subject: user.ID}, Header: &jwt.Header{Extra: map[string]interface{}{"alg":"RS256"}}} Defensive patterns
Strategy: type-guard
Validate before calling
if _, ok := req.GetSession().(JWTSessionContainer); !ok {
return fmt.Errorf("token endpoint misconfigured: session %T does not implement JWTSessionContainer", req.GetSession())
} Type guard
func asJWTSession(s fosite.Session) (JWTSessionContainer, bool) {
js, ok := s.(JWTSessionContainer)
return js, ok
} Try / catch
resp, err := oauth2Client.GetAccessToken(ctx, req)
if err != nil && strings.Contains(err.Error(), "must be of type JWTSessionContainer") {
log.Fatalf("config error: jwt strategy requires JWTSessionContainer sessions: %v", err)
} Prevention
- Pair the jwt access token strategy with a session type that embeds JWTSessionContainer (e.g. oauth2.JWTSession)
- Keep one session factory used by all token handlers so the session type can't drift
- Add an integration test that performs a token request with the jwt strategy enabled
- Check fosite docs when switching strategies — session types differ between hmac and jwt
When it happens
Trigger: Calling GenerateAccessToken (or any generate-path) on a strategy built with DefaultJWTStrategy while the request's GetSession() returns a plain/default session (e.g. fosite's DefaultSession or a custom session not implementing JWTSessionContainer) instead of a JWT-capable session (e.g. handler/oauth2.JWTSession or an HMACSession wrapper implementing GetJWTClaims).
Common situations: Switching the access token strategy to jwt in config without changing the session store/manager to create JWTSessionContainer sessions; custom Session types used with the default strategy; upgrading fosite where session wiring was changed.
Related errors
- GetTokenClaims() must not be nil
- failed to set token lifespans due to failed client type asse
- a secret for signing HMAC-SHA512/256 is expected to be defin
- header, body and signature must all be set
- Token is expired
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/b028f98b44299760.
Report an issue: GitHub.