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 }