61 lines
2.2 KiB
Go
61 lines
2.2 KiB
Go
|
|
package middleware
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
)
|
||
|
|
|
||
|
|
// ctxKey is an unexported type for request-scoped authentication values.
|
||
|
|
// Using a distinct type (rather than a bare string) keeps our keys out of
|
||
|
|
// collision range for any other package that also calls context.WithValue,
|
||
|
|
// and silences go vet's SA1029.
|
||
|
|
type ctxKey string
|
||
|
|
|
||
|
|
const (
|
||
|
|
ctxKeyUserAddress ctxKey = "user_address"
|
||
|
|
ctxKeyUserTrack ctxKey = "user_track"
|
||
|
|
ctxKeyAuthenticated ctxKey = "authenticated"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Default track level applied to unauthenticated requests (Track 1 = public).
|
||
|
|
const defaultTrackLevel = 1
|
||
|
|
|
||
|
|
// ErrMissingAuthorization is returned by extractAuth when no usable
|
||
|
|
// Authorization header is present on the request. Callers should treat this
|
||
|
|
// as "no auth supplied" rather than a hard failure for optional-auth routes.
|
||
|
|
var ErrMissingAuthorization = errors.New("middleware: authorization header missing or malformed")
|
||
|
|
|
||
|
|
// ContextWithAuth returns a child context carrying the supplied
|
||
|
|
// authentication state. It is the single place in the package that writes
|
||
|
|
// the auth context keys.
|
||
|
|
func ContextWithAuth(parent context.Context, address string, track int, authenticated bool) context.Context {
|
||
|
|
ctx := context.WithValue(parent, ctxKeyUserAddress, address)
|
||
|
|
ctx = context.WithValue(ctx, ctxKeyUserTrack, track)
|
||
|
|
ctx = context.WithValue(ctx, ctxKeyAuthenticated, authenticated)
|
||
|
|
return ctx
|
||
|
|
}
|
||
|
|
|
||
|
|
// UserAddress returns the authenticated wallet address stored on ctx, or
|
||
|
|
// "" if the context is not authenticated.
|
||
|
|
func UserAddress(ctx context.Context) string {
|
||
|
|
addr, _ := ctx.Value(ctxKeyUserAddress).(string)
|
||
|
|
return addr
|
||
|
|
}
|
||
|
|
|
||
|
|
// UserTrack returns the access tier recorded on ctx. If no track was set
|
||
|
|
// (e.g. the request bypassed all auth middleware) the caller receives
|
||
|
|
// Track 1 (public) so route-level checks can still make a decision.
|
||
|
|
func UserTrack(ctx context.Context) int {
|
||
|
|
if track, ok := ctx.Value(ctxKeyUserTrack).(int); ok {
|
||
|
|
return track
|
||
|
|
}
|
||
|
|
return defaultTrackLevel
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsAuthenticated reports whether the current request carried a valid auth
|
||
|
|
// token that was successfully parsed by the middleware.
|
||
|
|
func IsAuthenticated(ctx context.Context) bool {
|
||
|
|
ok, _ := ctx.Value(ctxKeyAuthenticated).(bool)
|
||
|
|
return ok
|
||
|
|
}
|