Basics: Basic Auth header

Intro - Basic Auth
Auth headers are not something overly complex, but we all come across them while dealing with APIs. Different tools handle them a bit differently. It’s not that annoying that learned it by heart but then I lost dev time every time I had to look it up. So. Here we go. Also… there might be madly intersting happenings in the AI world where new models beat each other in benchmarking every other week (at the time of writing according to livebench.ai o3-mini is the best one for coding and o1 the best reasoning model). The only logical step to take is to write about something which is 25y+ old. - hereby I prodly present my take on Basic Auth.
What are auth headers?
Auth headers are a way to authenticate a request to an API. They are a set of key-value pairs that are sent with the request. The most common auth header is the Authorization
header.
Basic Auth
What is it?
Basic Auth is one of the simplest authentication methods where credentials are sent in the HTTP header. The header is constructed by combining username and password with a colon (username:password
), encoding it in Base64, and prefixing it with “Basic ”. Read as “Basic username:password”.
Why are the Basic Auth credentials encoded?
The Base64 encoding requirement comes from RFC 7617, which defines the Basic Authentication scheme. The encoding serves two purposes:
- It allows the transmission of non-ASCII characters in usernames and passwords
- It avoids the use of forbidden characters in HTTP headers like colons, which are used as delimiters
The encoding process works as follows:
- The username and password are combined with a colon (
:
) - The resulting string is encoded into octets using UTF-8
- The octets are encoded using Base64 to create the credentials
- The word “Basic” and a space are prepended to the credentials
Note that Base64 encoding is not a security measure - it’s merely an encoding scheme to ensure safe transmission of the credentials as part of the HTTP Authorization header.
How to use Basic Auth?
Here’s how to use Basic Auth in different tools and languages:
-
in postman: Postman has a Basic Auth tab where you can paste your username and password. If you happen to have an API key, you can paste that in as well, just leave the username empty. The API key will be used as the password. Postman automatically handles the Base64 encoding.
-
in insomnia: Similar to Postman, select “Basic Auth” from the auth dropdown and enter your credentials. Insomnia handles the encoding automatically.
-
in curl: You can use the -u flag (for username and password) or manually with the header:
# Using the -u flag - username and password are plain text curl -u username:password https://domain.com/api/data # Or manually set the header and encode the credentials curl -H "Authorization: Basic $(echo -n username:password | base64)" \ https://domain.com/api/data
When using with base64, it’s important that the encoded string encorporates the colon.
-
in JavaScript: There are some ways to do this. It all comes down to the
btoa()
function which is a built-in function that encodes a string to a Base64 encoded string. You guessed it right, there is a reverse function calledatob()
that decodes the Base64 encoded string.// Method 1: Using axios with auth object in the options to pass // the username and password which is then encoded to a // Base64 string under the hood, just like in postman or curl const axios = require('axios'); axios.get('https://domain.com/api/data', { auth: { username: 'username', password: 'password' } });
// Method 2: Using axios with and pass the Authorization header manually const axios = require('axios'); axios.get('https://domain.com/api/data', { headers: { 'Authorization': 'Basic ' + btoa('username:password') } });
You can also use
fetch
to do the same thing. -
in Python:
import requests import base64 # Method 1: Let requests handle it response = requests.get('https://domain.com/api/data', auth=('username', 'password')) # Method 2: Manual header construction credentials = base64.b64encode(b'username:password').decode('utf-8') headers = {'Authorization': f'Basic {credentials}'} response = requests.get('https://domain.com/api/data', headers=headers)
Security notes:
- The credentials are encoded but not encrypted! Base64 encoding provides no confidentiality protection
- Always use HTTPS (TLS) when using Basic Auth to protect against man-in-the-middle attacks or eavesdropping
- Basic Auth credentials are sent with every request as there is no session mechanism (unlike in a token-based system, OAuth, Cookie-based auth, etc.)
- The server must take precautions against timing attacks when comparing credentials
- Servers should implement request throttling to prevent brute-force attacks
Additional thought, desribed in the RFC 7617 directly: If you authenticate yourself somewhere using Basic Auth, keep in mind that you are in no control of what the server does with your credentials. It’s basically the same as if you would send your password in plain text. So if the server stores your requests / credentials / both, you basically handed over your password to the system on a silver platter. Should the server be compromised, your credentials are free for take. Should the server be malicious, your credentials are free for take. Etc. So never use the same password twice across different systems as it could grant access to multiple accounts of yours in case of a data breach or maliciuos activity.
Why is it still used?
- Simplicity: Basic Auth is super easy to implement and understand
- Backward compatibility: Many older APIs still use Basic Auth
- Wide browser support: Basic Auth is supported by all major browsers
When should you use Basic Auth?
- Simple API authentication: For small, internal APIs where security is not a major concern
- Legacy systems: When integrating with legacy systems that use Basic Auth
- Public APIs: For APIs that are not sensitive and where the risk of credential exposure is low
- API docs: Basic Auth is supported by OpenAPI 3.0 docs
Conclusion
I still think that there are valid use cases for Basic Auth even with its securuty vulnerabilities, even after 25 years+ of its existence, but it’s important to understand the security implications and use it accordingly.