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>
49 lines
1.2 KiB
Go
49 lines
1.2 KiB
Go
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)
|
|
}
|