Secure API with Basic Authentication in Go
This challenge focuses on implementing a simple API endpoint secured with Basic Authentication in Go. Basic Authentication is a straightforward method where the client sends credentials (username and password) in each request, which the server verifies. This exercise will help you understand the fundamentals of authentication and how to protect API endpoints.
Problem Description
You are tasked with creating a Go program that exposes a protected API endpoint. This endpoint should only be accessible to clients who provide valid username and password credentials via Basic Authentication. The server should:
- Handle HTTP requests: Listen for incoming HTTP requests on a specified port (e.g., 8080).
- Authenticate requests: For requests to the protected endpoint (
/api/protected), extract the username and password from theAuthorizationheader. The header should be in the formatAuthorization: Basic <base64 encoded username:password>. - Verify credentials: Compare the extracted username and password against a predefined set of valid credentials (e.g., "user:password").
- Respond appropriately:
- If the credentials are valid, return a success message (e.g., "Access Granted").
- If the credentials are invalid, return a
401 Unauthorizederror with aWWW-Authenticateheader indicating Basic Authentication is required. - If the request is to a different endpoint, respond with a
404 Not Found.
- Base64 Decode: Properly decode the Base64 encoded username and password from the
Authorizationheader.
Key Requirements:
- Use the
net/httppackage for handling HTTP requests. - Use the
encoding/base64package for Base64 decoding. - Implement proper error handling.
- The code should be well-structured and readable.
Examples
Example 1:
Input:
HTTP Request to /api/protected with Authorization: Basic dXNlckBwYXNlYXI=
(where "dXNlckBwYXNlYXI=" is the Base64 encoding of "user:password")
Output:
HTTP Response: 200 OK
Body: Access Granted
Explanation: The request includes a valid Authorization header. The server decodes the header, verifies the credentials "user:password", and returns a success message.
Example 2:
Input:
HTTP Request to /api/protected with Authorization: Basic invalidbase64string
Output:
HTTP Response: 401 Unauthorized
Headers: WWW-Authenticate: Basic realm="Protected Area"
Body: (Empty or an error message)
Explanation: The request includes an invalid Base64 encoded string in the Authorization header. The server returns a 401 Unauthorized error, prompting the client to authenticate.
Example 3:
Input:
HTTP Request to /api/public
Output:
HTTP Response: 404 Not Found
Explanation: The request is to a non-existent endpoint. The server returns a 404 Not Found error.
Constraints
- The server should listen on port 8080 (or a configurable port).
- Valid credentials are: "user:password".
- The Base64 encoding should be standard Base64.
- The
WWW-Authenticateheader in the 401 response should includerealm="Protected Area". - The program should handle potential errors during Base64 decoding gracefully.
- The solution should be implemented in Go.
Notes
- Consider using the
http.HandlerFunctype for defining the request handler. - The
Authorizationheader is case-insensitive, but the decoding process must be correct regardless of the case. - Focus on the core authentication logic; error handling for other HTTP methods (e.g., PUT, DELETE) is not required.
- You can use a simple
ifstatement to compare the username and password against the predefined credentials. More sophisticated authentication mechanisms (e.g., hashing, database storage) are beyond the scope of this challenge. - Remember to import the necessary packages.
- Test your solution thoroughly with both valid and invalid credentials, as well as requests to different endpoints.