IntegrAuth Academy
Identity, security and practical AI — free, from zero. Byte-sized lessons, real diagrams, hands-on labs, zero fluff. Two programs, each with its own exam and certificate.
English is hard? Your browser can translate this page into Tamil, Telugu, Kannada, Malayalam or Hindi. Tech words stay in English so you learn the real names.
How?
- Chrome on phone: ⋮ menu → Translate
- Chrome on computer: right-click → Translate to …
- Edge: the translate icon in the address bar
Basic, bearer & the Authorization header
Every credential on the sign-in menu travels inside an HTTP request. Your goal: send credentials the safe way, and read 401 and 403 answers.
- Send credentials in the Authorization header, never in the URL.
- Basic is a Base64-encoded password. Anyone can decode it.
- Basic splits at the first colon.
- 401 means no valid credentials. 403 means known, but not allowed.
- Hide credentials in logs.
One header, many schemes
HTTP has one standard place to prove who you are: the Authorization header. It holds a scheme name, a space, then the credentials. Three common schemes:
Authorization: Basic bWF5YTpzM2NyZXQ=— a username and password.Authorization: Bearer eyJhbGciOi…— an OAuth access token.Authorization: DPoP eyJhbGciOi…— a token tied to a key. A separate DPoP proof header comes with it. See stolen-token defenses II.
If a request has no valid credentials, the server answers 401 Unauthorized. It MUST add a WWW-Authenticate header. It names the scheme the server wants. Example: WWW-Authenticate: Bearer realm="orders". See HTTP basics.
Basic: a password in thin disguise
Basic joins username:password with a colon. Then it Base64-encodes the result. bWF5YTpzM2NyZXQ= is just maya:s3cret. Anyone can decode it, with no key. That is encoding, not encryption. So use Basic only inside TLS (the https padlock).
The first colon splits the two parts. A username can never contain a colon. A password can. So admin:P@ss:w0rd means user admin and password P@ss:w0rd.
A machine can use Basic to sign in to an OAuth token endpoint (client_secret_basic). The client id and client secret go in the header. Both must be URL-encoded before Base64. If not, a secret with + or % fails with invalid_client.
Bearer: holding it is permission
A bearer token works for whoever holds it. Send it in the Authorization header. Never put it in the URL, like ?access_token=….
Why web addresses leak, even over HTTPS
Over HTTPS, the path and the query string are encrypted on the wire. The leak happens at the two ends. People treat a URL as a harmless label and copy it everywhere:
- Logs. Servers, proxies and gateways write the full URL of every request. A line like
GET /v1/orders?api_key=k_live_7Qm…can sit there for a year. - Browser history and bookmarks keep every URL.
- The Referer header tells the next page where you came from. It carries the full URL on requests to the same site. Browsers trim it to the site name when you go to another site.
Put an API key in a header, such as X-API-Key. Never put it in the query. Found one in a log? Rotate the key and make the API reject credentials in query strings.
mailing a house key. The header puts the key inside the sealed envelope. The URL tapes it to the outside, next to the address. Every post office that writes down the address now knows your key.
When the server says no: 401 or 403?
Two status codes carry most refusals.
- 401 means: "I have no valid credentials from you." Get a valid token and retry. This also holds when the token is expired, revoked or malformed (
invalid_token). - 403 means: "I know who you are, and the answer is still no." The error
insufficient_scopemeans the app needs more permission. A new token of the same kind will not help. - 400 with
invalid_requestmeans the request is broken. For example, the token was sent two ways at once. Fix the request.
Go deeper: Bearer rules and error table
RFC 6750 allows three ways to send a bearer token. The Authorization header is the one every server MUST support. A form-body field is allowed only in narrow cases. A query parameter was allowed in 2012 with a warning. RFC 9700 (January 2025) says clients MUST NOT use it. A client must not use two methods in one request.
| What went wrong | Status | Challenge | What the client does |
|---|---|---|---|
| No credentials | 401 | Bearer realm="orders" | Get a token and send it. |
| Token expired, revoked or malformed | 401 | error="invalid_token" | Get a fresh token and retry. |
| Valid token, not enough permission | 403 | error="insufficient_scope", scope="orders:write" | Ask for more permission. |
| Broken request | 400 | error="invalid_request" | Fix the request. |
With client_secret_post, the client sends the secret in the form body. RFC 6749 says this is NOT RECOMMENDED unless the client cannot use Basic. The values MUST NOT go in the web address. Either way it is a shared secret. The menu shows stronger options.
Keep error messages short and generic. "The access token expired" helps a real client. A message that says which check failed helps an attacker.
A header is safer than a URL, but not magic. "Log full requests" puts every Authorization header in the logs. Hide Authorization, Proxy-Authorization, Cookie, Set-Cookie and your API-key header. Never log token request and response bodies.
🧪 Interactive lab — enable JavaScript to play with this one.
Use made-up credentials only. Run curl -v -u demo:demo https://httpbin.org/basic-auth/demo/demo to see the Authorization: Basic header. Decode it with echo ZGVtbzpkZW1v | base64 --decode. Then call https://httpbin.org/bearer with no header and read the WWW-Authenticate challenge in the 401 reply. (httpbin.org is a free HTTP testing service.)