Mint and verify short-lived RS256 user tokens.
ExApps sign after AppAPI auth; Microservices check a static public key or an OIDC issuer and forward the same bearer. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
package usertoken
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// ErrUnauthorized is wrapped by every failed token check.
|
||||
// Startup and configuration failures do not wrap it.
|
||||
var ErrUnauthorized = errors.New("unauthorized")
|
||||
|
||||
// Caller is the user a verified token names.
|
||||
// Groups is nil when the token omitted the claim, and non-nil (possibly empty)
|
||||
// when the claim was present.
|
||||
type Caller struct {
|
||||
Subject string
|
||||
Username string
|
||||
Groups []string
|
||||
}
|
||||
|
||||
type ctxKey int
|
||||
|
||||
const (
|
||||
ctxCaller ctxKey = iota
|
||||
ctxBearer
|
||||
)
|
||||
|
||||
// CallerFromContext returns the user [Auth.Middleware] stored.
|
||||
func CallerFromContext(ctx context.Context) (Caller, bool) {
|
||||
c, ok := ctx.Value(ctxCaller).(Caller)
|
||||
return c, ok
|
||||
}
|
||||
|
||||
// BearerFromContext returns the raw JWT [Auth.Middleware] stored, without the
|
||||
// "Bearer " prefix. Outbound calls send "Bearer " plus this string.
|
||||
func BearerFromContext(ctx context.Context) (string, bool) {
|
||||
s, ok := ctx.Value(ctxBearer).(string)
|
||||
return s, ok
|
||||
}
|
||||
|
||||
func withAuth(ctx context.Context, c Caller, raw string) context.Context {
|
||||
ctx = context.WithValue(ctx, ctxCaller, c)
|
||||
return context.WithValue(ctx, ctxBearer, raw)
|
||||
}
|
||||
|
||||
func unauthorized(msg string) error {
|
||||
return errors.Join(errors.New(msg), ErrUnauthorized)
|
||||
}
|
||||
Reference in New Issue
Block a user