fix: set authenticated user on request context in bearer token auth

tryBearerAuth validated the bearer token but never looked up the
associated user or set it on the request context. This meant
downstream handlers calling GetCurrentUser would get nil even
with a valid token.

Changes:
- Add ContextWithUser/UserFromContext helpers in auth package
- tryBearerAuth now looks up the user by token's UserID and
  sets it on the request context via auth.ContextWithUser
- GetCurrentUser checks context first before falling back to
  session cookie
- Add integration tests for bearer auth user context
This commit is contained in:
clawbot
2026-02-19 13:54:09 -08:00
parent dde0ad5250
commit 160b02b0b6
5 changed files with 218 additions and 24 deletions

View File

@@ -26,6 +26,21 @@ const (
sessionUserID = "user_id"
)
// contextKeyUser is the context key for storing the authenticated user.
type contextKeyUser struct{}
// ContextWithUser returns a new context with the given user attached.
func ContextWithUser(ctx context.Context, user *models.User) context.Context {
return context.WithValue(ctx, contextKeyUser{}, user)
}
// UserFromContext retrieves the user from the context, if set.
func UserFromContext(ctx context.Context) *models.User {
user, _ := ctx.Value(contextKeyUser{}).(*models.User)
return user
}
// Argon2 parameters.
const (
argonTime = 1
@@ -239,6 +254,11 @@ func (svc *Service) GetCurrentUser(
ctx context.Context,
request *http.Request,
) (*models.User, error) {
// Check context first (set by bearer token auth).
if user := UserFromContext(ctx); user != nil {
return user, nil
}
session, sessionErr := svc.store.Get(request, sessionName)
if sessionErr != nil {
// Session error means no user - this is not an error condition

View File

@@ -82,7 +82,7 @@ type deploymentLogWriter struct {
lineBuffer bytes.Buffer // buffer for incomplete lines
mu sync.Mutex
done chan struct{}
flushed sync.WaitGroup // waits for flush goroutine to finish
flushed sync.WaitGroup // waits for flush goroutine to finish
flushCtx context.Context //nolint:containedctx // needed for async flush goroutine
}