# Authorization Header: Bearer, Basic and 401 Fixes

> Authorization header carries credentials as scheme plus token. Bearer and Basic formats, WWW-Authenticate, why proxies strip it, redirects, CORS and storage.

Source: https://howhttpworks.com/headers/authorization
Last reviewed: 2026-10-04

> **TL;DR:** `Authorization: <scheme> <credentials>` proves who is calling. Use `Bearer <token>` for APIs and `Basic base64(user:pass)` only over HTTPS; if the server says 401, check the `WWW-Authenticate` response header for the scheme it wants.

## Format

```http
GET /api/profile HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.abc123
```

A missing or rejected credential gets a challenge that names the scheme:

```http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api", error="invalid_token", error_description="The access token expired"
```

RFC 9110 section 11.6.2 defines the header; schemes are registered with IANA. Common ones: `Basic` (RFC 7617), `Bearer` (RFC 6750), `Digest` (rare), `Negotiate` (Kerberos/NTLM), `AWS4-HMAC-SHA256` (SigV4), and `DPoP` (RFC 9449, sender-constrained tokens). "API key" is not a scheme; people send keys as `Bearer`, or in `X-API-Key`.

## Bearer

Whoever holds the token can use it, which is why lifetime and transport matter:

```bash
curl -H "Authorization: Bearer $TOKEN" https://api.example.com/me
```

The 401 `WWW-Authenticate` error values come from RFC 6750: `invalid_request` (400), `invalid_token` (401), `insufficient_scope` (403). Expired tokens, wrong audience, clock skew on JWT `exp` or `nbf`, and a missing `Bearer ` prefix are the usual reasons for `invalid_token`.

## Basic

`base64("user:pass")`, sent on every request:

```bash
curl -u alice:s3cret https://example.com/admin -v
# > Authorization: Basic YWxpY2U6czNjcmV0
echo YWxpY2U6czNjcmV0 | base64 -d
```

base64 is encoding, not encryption. Browsers show a native login prompt when a 401 carries `WWW-Authenticate: Basic realm="Admin"`. Basic is fine for internal tools behind TLS, bad for anything else. Compare passwords with a constant-time function and rate-limit attempts.

## Why the header goes missing

- **Cross-origin redirect.** Per the Fetch Standard, browsers strip `Authorization` when a redirect leaves the origin; curl does the same unless you pass `--location-trusted`. A 301 from `http://` to `https://` or from `example.com` to `www.example.com` drops it.
- **Proxy or FastCGI.** Apache with `mod_fcgid`/PHP-FPM may not pass it; add `SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1` or `RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]`. nginx forwards it by default with `proxy_pass`, but `proxy_set_header Authorization ""` or a custom `fastcgi_param HTTP_AUTHORIZATION $http_authorization;` is needed for FastCGI. AWS API Gateway authorizers and some CDNs may replace it.
- **CORS.** `Authorization` is not a safelisted header, so a cross-origin call triggers a preflight, and the response needs `Access-Control-Allow-Headers: authorization`. A wildcard `*` in that header does not cover `Authorization`; list it explicitly. See [Access-Control-Allow-Headers](https://howhttpworks.com/headers/access-control-allow-headers).
- **Caching.** A shared cache will not store a response to a request with `Authorization` unless the response has `public`, `s-maxage` or `must-revalidate` (RFC 9111 section 3.5). Add `Vary: Authorization` if you intentionally cache.

## 401 or 403

401 means the server did not accept who you are, so send credentials or fresh ones. 403 means it knows who you are and refuses. See [401 vs 403](https://howhttpworks.com/compare/401-vs-403), [401](https://howhttpworks.com/status-codes/401) and [403](https://howhttpworks.com/status-codes/403).

## Token storage in browsers

A token in `localStorage` sent as `Bearer` is immune to CSRF, but any XSS can read and exfiltrate it. An `HttpOnly; Secure; SameSite=Lax` cookie cannot be read by script but is attached automatically, so you need CSRF defences for state-changing requests. For a first-party SPA the cookie (or a backend-for-frontend that holds tokens server-side) is usually the safer choice. For mobile apps and third-party API clients, use `Authorization: Bearer` with short-lived access tokens (minutes) and rotating refresh tokens. See [Cookie security](https://howhttpworks.com/guides/cookie-security) and [Authentication](https://howhttpworks.com/guides/authentication).

## Security checklist

- Only over HTTPS; add [Strict-Transport-Security](https://howhttpworks.com/headers/strict-transport-security).
- Redact `Authorization` and `Cookie` in access logs, APM, and error reporters.
- Never put credentials in the URL; they leak via `Referer`, history and logs.
- Pin the verification algorithm for JWTs and validate `aud`, `iss`, `exp`.
- Send `Cache-Control: no-store` on token endpoints.

## Related

- [WWW-Authenticate](https://howhttpworks.com/headers/www-authenticate), [Proxy-Authorization](https://howhttpworks.com/headers/proxy-authorization), [Authentication-Info](https://howhttpworks.com/headers/authentication-info), [Cookie](https://howhttpworks.com/headers/cookie)
