Skip to main content

JWT & Session callbacks

Two callbacks shape what clients see: JWT (token claims) and Session (JSON from GET /auth/session).

JWT callback

Runs when building or refreshing encrypted tokens (JWT strategy + bearer access tokens).

JWT: func(ctx context.Context, p goauth.JWTCallbackParams) (goauth.JWT, error) {
// mutate p.Token map, return it
return p.Token, nil
},

JWTCallbackParams

type JWTCallbackParams struct {
Token JWT // existing claims
User *User
Account *Account
Profile Profile
Trigger string // "signIn", "signUp", "update"
IsNewUser bool
}

Example: add roles (simple)

JWT: func(ctx context.Context, p goauth.JWTCallbackParams) (goauth.JWT, error) {
if p.User != nil {
roles, _ := db.RolesForUser(ctx, p.User.ID)
p.Token["roles"] = roles
p.Token["role"] = firstRole(roles) // fiberauth HasRole compatibility
}
return p.Token, nil
},

Example: tenant / org claim (advanced)

JWT: func(ctx context.Context, p goauth.JWTCallbackParams) (goauth.JWT, error) {
if p.Trigger == "signIn" && p.User != nil {
org, err := db.PrimaryOrg(ctx, p.User.ID)
if err != nil {
return nil, err
}
p.Token["org"] = org.Slug
p.Token["orgId"] = org.ID
}
return p.Token, nil
},

Reading claims in handlers

session, _ := auth.GetSession(w, r)
if session.HasRole("admin") {
// ...
}
slug := session.StringClaim("org")

Works with fiberauth Guard + HasRole.

Token refresh

POST /auth/token runs the JWT callback with Trigger: "update" (user may be nil — only refresh claims you can derive from token).


Session callback

Runs before returning session JSON to the client.

Session: func(ctx context.Context, p goauth.SessionCallbackParams) (*goauth.Session, error) {
return p.Session, nil
},

SessionCallbackParams

FieldJWT strategyDatabase strategy
SessionPopulatedPopulated
TokenJWT mapSet
UserFrom tokenLoaded from DB

Example: hide internal fields (simple)

Session: func(ctx context.Context, p goauth.SessionCallbackParams) (*goauth.Session, error) {
s := p.Session
if s != nil && s.User != nil {
// client session JSON won't include adapter-internal data
s.User = &goauth.User{
ID: s.User.ID,
Email: s.User.Email,
Name: s.User.Name,
}
}
return s, nil
},

Example: expose safe claims to frontend (advanced)

Session: func(ctx context.Context, p goauth.SessionCallbackParams) (*goauth.Session, error) {
s := p.Session
if s == nil {
return nil, nil
}
// Session embeds JWT claims for client read via session.Claim()
return s, nil
},

Order of execution

SignIn → resolveUser → issueSession
→ JWT callback (jwt strategy)
→ set cookie OR build TokenResponse
→ Session callback
→ write response

Default token claims

defaultToken(user) sets sub, name, email, picture, iat, exp. JWT callback extends this map.

Bearer TokenResponse also includes sessionId (UUID v4) from buildTokenResponse.