MCPcopy Index your code
hub / github.com/coder/coder / ExtractAPIKey

Function ExtractAPIKey

coderd/httpmw/apikey.go:577–700  ·  view source on GitHub ↗

ExtractAPIKey requires authentication using a valid API key. It handles extending an API key if it comes close to expiry, updating the last used time in the database. If the configuration specifies that the API key is optional, a nil API key and authz object may be returned. False is returned if a

(rw http.ResponseWriter, r *http.Request, cfg ExtractAPIKeyConfig)

Source from the content-addressed store, hash-verified

575// to the request and the caller should give up.
576// nolint:revive
577func ExtractAPIKey(rw http.ResponseWriter, r *http.Request, cfg ExtractAPIKeyConfig) (*database.APIKey, *rbac.Subject, bool) {
578 ctx := r.Context()
579 // Write wraps writing a response to redirect if the handler
580 // specified it should. This redirect is used for user-facing pages
581 // like workspace applications.
582 write := func(code int, response codersdk.Response) (apiKey *database.APIKey, subject *rbac.Subject, ok bool) {
583 if cfg.RedirectToLogin {
584 RedirectToLogin(rw, r, nil, response.Message)
585 return nil, nil, false
586 }
587
588 // Add WWW-Authenticate header for 401/403 responses (RFC 6750 + RFC 9728)
589 if code == http.StatusUnauthorized || code == http.StatusForbidden {
590 rw.Header().Set("WWW-Authenticate", buildWWWAuthenticateHeader(cfg.AccessURL, r, code, response))
591 }
592
593 httpapi.Write(ctx, rw, code, response)
594 return nil, nil, false
595 }
596
597 // optionalWrite wraps write, but will return nil, true if the API key is
598 // optional.
599 //
600 // It should be used when the API key is not provided or is invalid,
601 // but not when there are other errors.
602 optionalWrite := func(code int, response codersdk.Response) (*database.APIKey, *rbac.Subject, bool) {
603 if cfg.Optional {
604 return nil, nil, true
605 }
606
607 write(code, response)
608 return nil, nil, false
609 }
610
611 // --- Consume prechecked result if available ---
612 // Skip prechecked data when cfg has a custom SessionTokenFunc,
613 // because the precheck used the default token extraction and may
614 // have validated a different token (e.g. workspace app token
615 // issuance in workspaceapps/db.go).
616 var key *database.APIKey
617 var actor rbac.Subject
618 var userStatus database.UserStatus
619 var skipValidation bool
620
621 if cfg.SessionTokenFunc == nil {
622 if pc, ok := ctx.Value(apiKeyPrecheckedContextKey{}).(APIKeyPrechecked); ok {
623 if pc.Err != nil {
624 // Validation failed at the top level (includes
625 // "no token provided").
626 if pc.Err.Hard {
627 return write(pc.Err.Code, pc.Err.Response)
628 }
629 return optionalWrite(pc.Err.Code, pc.Err.Response)
630 }
631 // Valid — use prechecked data, skip to route-specific logic.
632 key = &pc.Result.Key
633 actor = pc.Result.Subject
634 userStatus = pc.Result.UserStatus

Callers 3

IssueMethod · 0.92
renderHTMLWithStateMethod · 0.92
ExtractAPIKeyMWFunction · 0.85

Calls 12

WriteFunction · 0.92
RedirectToLoginFunction · 0.85
ValidateAPIKeyFunction · 0.85
ContextMethod · 0.65
SetMethod · 0.65
ParseMethod · 0.65
writeFunction · 0.50
HeaderMethod · 0.45
ValueMethod · 0.45
ErrorMethod · 0.45

Tested by

no test coverage detected