Files
base/apis/record_auth_refresh.go
zeekayandHanzo Dev 007a8c8002 Superuser tokens come only from IAM
A migration replaces the _superusers token secrets once, so every
superuser token a Base signed itself stops verifying on the first
start. auth-refresh answers 403 for a superuser token that names no IAM
subject, and answers an IAM token as before.

The test data records the rotation as applied, so its tokens stand for
tokens signed after it.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-11 13:58:52 -07:00

42 lines
1.3 KiB
Go

package apis
import (
"github.com/hanzoai/base/core"
"github.com/hanzoai/base/tools/security"
"github.com/spf13/cast"
)
func recordAuthRefresh(e *core.RequestEvent) error {
record := e.Auth
if record == nil {
return e.NotFoundError("Missing auth record context.", nil)
}
// IAM issues and renews superuser tokens, and a token from IAM names its
// subject. A superuser token that names none was signed by a Base.
if sub, _ := e.Get(RequestEventKeySub).(string); sub == "" && record.IsSuperuser() {
return e.ForbiddenError("Superuser tokens are issued and renewed by IAM.", nil)
}
event := new(core.RecordAuthRefreshRequestEvent)
event.RequestEvent = e
event.Collection = record.Collection()
event.Record = record
return e.App.OnRecordAuthRefreshRequest().Trigger(event, func(e *core.RecordAuthRefreshRequestEvent) error {
token := Credential(e.Request)
// skip token renewal if the token's payload doesn't explicitly allow it (e.g. impersonate tokens)
claims, _ := security.ParseUnverifiedJWT(token) //
if v, ok := claims[core.TokenClaimRefreshable]; ok && cast.ToBool(v) {
var tokenErr error
token, tokenErr = e.Record.NewAuthToken()
if tokenErr != nil {
return e.InternalServerError("Failed to refresh auth token.", tokenErr)
}
}
return recordAuthResponse(e.RequestEvent, e.Record, token, "", nil)
})
}