cURL is a powerful and versatile command-line tool for making HTTP requests and transferring data. It supports a wide range of protocols and options, making it a go-to utility for developers to interact with web APIs. One common requirement when working with APIs is authentication – verifying your identity to access protected resources. A simple authentication mechanism built into the HTTP protocol is Basic Auth. In this guide, we‘ll take an in-depth look at how to use cURL to make requests with Basic Auth to authenticate to APIs.
Understanding Basic Authentication
Basic authentication is a simple challenge and response scheme included in the HTTP protocol. With Basic Auth, a client sends the username and password in the Authorization
header when making a request to a server. The credentials are formatted as a base64-encoded string of username:password
.
Here‘s what a raw HTTP request with Basic Auth looks like:
GET /api/protected-resource HTTP/1.1
Host: api.example.com
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
The Authorization
header contains the word "Basic" followed by a space and then the base64 encoded string of the username and password joined by a colon (username:password
).
When the server receives a request with Basic Auth credentials, it decodes the Authorization
header, extracting the username and password. It then compares them against its internal database of valid users. If there‘s a match, the server fulfills the request and returns the protected resource. If the credentials are missing or invalid, the server responds with a 401 Unauthorized
status, indicating authentication is required.
It‘s important to note that Basic Auth provides very minimal security. The username and password are sent in plaintext with every request, merely encoded with base64 which is trivially decoded. Anyone who intercepts the HTTP messages can easily extract the credentials. Basic Auth should only be used over a secure HTTPS connection to encrypt the sensitive data in transit. Even with HTTPS, Basic Auth may not be suitable for highly sensitive credentials, especially if the server stores the credentials in an insecure manner.
Making Authenticated Requests with cURL
With that background in mind, let‘s look at how to use cURL to send requests with Basic Auth. We‘ll be using the -u
or --user
option to pass the username and password to cURL.
Here‘s the basic syntax:
curl -u username:password URL
Or with the verbose --user
flag:
curl --user username:password URL
Replace username
and password
with your actual credentials, and URL
with the endpoint you want to access. cURL automatically encodes the credentials with base64 and includes them in the Authorization
header.
For example, let‘s say we want to access a protected resource at https://api.example.com/secret
that requires Basic Auth. The username is "AzureDiamond" and the password is "hunter2". Here‘s how we‘d make that request with cURL:
curl -u AzureDiamond:hunter2 https://api.example.com/secret
If the credentials are valid, the server will return the secret resource. If not, it will respond with a 401 Unauthorized error.
We can also use cURL‘s -v
or --verbose
flag to print out information about the request, including the headers:
curl -u AzureDiamond:hunter2 https://api.example.com/secret -v
In the output, we‘ll see the Authorization
header cURL generates:
> GET /secret HTTP/1.1
> Host: api.example.com
> Authorization: Basic QXp1cmVEaWFtb25kOmh1bnRlcjI=
The base64-encoded credentials are QXp1cmVEaWFtb25kOmh1bnRlcjI=
. If we decode that string, it reveals the username and password:
$ echo QXp1cmVEaWFtb25kOmh1bnRlcjI= | base64 --decode
AzureDiamond:hunter2
This demonstrates why Basic Auth is insecure over plaintext HTTP connections. It‘s trivial to extract the credentials from base64.
Providing Credentials in a Separate File
For convenience and to avoid having sensitive credentials in shell history, you can store them in a separate file in the format username:password
and tell cURL to read from that file with -u
using the @
syntax:
curl -u @creds.txt https://api.example.com/secret
Where the creds.txt
file contains:
AzureDiamond:hunter2
Making POST Requests with Basic Auth
So far we‘ve looked at making authenticated GET requests with cURL, but the same approach works for other HTTP methods like POST. Just add the -X POST
option to set the method and -d
to pass the request body:
curl -u AzureDiamond:hunter2 -X POST -d ‘{"message": "hello"}‘ https://api.example.com/post
This will send a POST request with the given JSON body and Basic Auth credentials.
Securing Sensitive Credentials
When working with sensitive data like passwords and API keys, it‘s crucial to handle them securely. Avoid hardcoding credentials into scripts or version control. Instead, use environment variables or secure secret management systems.
For example, instead of having the username and password directly in the cURL command, retrieve them from environment variables:
curl -u "$USERNAME:$PASSWORD" https://api.example.com/secret
Then provide the values when running the script:
USERNAME=AzureDiamond PASSWORD=hunter2 ./auth_example.sh
This way, the sensitive credentials are not stored in the script itself. Make sure to avoid printing secrets to stdout/stderr or logging them.
When storing credentials on disk temporarily, ensure the file permissions are set appropriately so only authorized users can read them. Securely erase the files after use with a utility like shred
.
Automating Authenticated Requests
Using cURL with Basic Auth can be easily integrated into shell scripts and CI/CD pipelines for automated, authenticated interactions with APIs.
For example, we can write a simple shell script to make multiple authenticated requests:
#!/bin/bash
USERNAME=AzureDiamond
PASSWORD=hunter2
API_URL=https://api.example.com
curl -u "$USERNAME:$PASSWORD" "$API_URL/resource1"
curl -u "$USERNAME:$PASSWORD" "$API_URL/resource2"
curl -u "$USERNAME:$PASSWORD" "$API_URL/resource3"
This script sets the username, password, and base API URL as variables, then makes authenticated requests to several endpoints.
We can also use cURL in CI/CD pipelines to run API tests or perform authenticated deployments. For example, here‘s how we might use cURL with Basic Auth in a GitHub Actions workflow:
name: API Tests
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run API tests
env:
USERNAME: ${{ secrets.API_USERNAME }}
PASSWORD: ${{ secrets.API_PASSWORD }}
run: |
curl -u "$USERNAME:$PASSWORD" https://api.example.com/test1
curl -u "$USERNAME:$PASSWORD" https://api.example.com/test2
This workflow uses GitHub‘s encrypted secrets feature to securely provide the API credentials as environment variables. The curl
commands then reference those environment variables to authenticate.
cURL Alternatives for Basic Auth
While cURL is a popular choice for making HTTP requests with Basic Auth, there are many other tools and libraries that support authenticated requests. Here are a few cURL alternatives:
-
Postman – A GUI tool for building and testing APIs. Provides an easy way to configure Basic Auth.
-
HTTPie – A user-friendly command-line HTTP client with intuitive syntax. Supports Basic Auth with
--auth username:password
. -
Axios – A promise-based HTTP client for JavaScript. Provides an
auth
option to configure Basic Auth. -
Requests – A simple and powerful HTTP library for Python. Has built-in support for Basic Auth authentication.
These tools can be useful if you prefer a graphical interface over cURL‘s command-line approach or if you need to integrate Basic Auth into an application using one of the supported languages.
Conclusion
Basic authentication is a simple way to protect access to web resources. While it has its limitations in terms of security, Basic Auth can be appropriate for some internal or low-risk APIs. With cURL, we can easily test APIs that use Basic Auth or script authenticated interactions.
Remember to always use HTTPS to encrypt sensitive credentials in transit, and take care to securely handle and store secrets. We covered several best practices like using environment variables and secure secret management.
By understanding how to set the Authorization
header and provide credentials with cURL‘s -u
flag, you‘re equipped to work with a wide variety of APIs and services that use Basic Auth. As we saw, integrating cURL into shell scripts and CI/CD pipelines enables powerful automation workflows.
I hope this deep dive into using cURL with Basic Auth has been helpful! Let me know if you have any other questions.