Implementing OAuth 2.0 Authorization Code Flow and Secure Token Storage
IntroductionCopied!
In today's digital landscape, secure authentication and authorization are vital for protecting user data and providing a seamless user experience. This documentation guides you through integrating the OAuth 2.0 Authorization Code Flow into your application and outlines best practices for securely storing access and refresh tokens.
Understanding OAuth 2.0Copied!
What is OAuth 2.0?
OAuth 2.0 is an industry-standard authorization framework that enables applications to obtain limited access to user accounts on an HTTP service. It allows users to grant third-party applications access to their resources without sharing their credentials.
OAuth 2.0 Grant Types
OAuth 2.0 defines several grant types for different scenarios:
-
Authorization Code Grant: Ideal for server-side applications where the client secret can be securely stored.
-
Implicit Grant: Used in client-side applications like mobile apps and web applications running in a browser.
-
Resource Owner Password Credentials Grant: Direct exchange of user credentials (less secure, generally discouraged).
-
Client Credentials Grant: Used for application-level access without user involvement.
-
Refresh Token Grant: Used to obtain a new access token when the current one expires.
Authorization Code FlowCopied!
Flow Overview
The Authorization Code Flow is a secure method for obtaining access and refresh tokens necessary for accessing protected resources on behalf of a user. This flow is suitable for applications where the client secret can be securely stored.
Key Characteristics:
-
User Interaction: The user explicitly authorizes the application by clicking a button like "I authorize this application."
-
Exchange of Authorization Code: An authorization code is exchanged for access and refresh tokens.
-
Long-Term Access: Tokens can be stored long-term to maintain access until the user revokes permissions.
Implementing the Flow with Provided Endpoints
This section provides specific URLs and endpoints based on our authentication server configuration. We will use shell commands to demonstrate the requests.
1. Application Registration
-
Client ID:
YOUR_CLIENT_ID
-
Client Secret:
YOUR_CLIENT_SECRET
-
Authorization Server URL:
https://auth.janebunn.website/realms/janesweather
2. Set your rediredt URL
-
Redirect URI:
http://localhost:8000/callback
Ensure that this URI is registered with the authorization server (contact us).
3. Initiate Authorization Request
Construct the authorization URL to redirect the user to the authorization server.
Authorization Endpoint:
https://auth.janebunn.website/realms/janesweather/protocol/openid-connect/auth
Parameters:
-
response_type=code
-
client_id=YOUR_CLIENT_ID
-
redirect_uri=http://localhost:8000/callback
Example Authorization URL:
4. User Authorization
-
User Action: The user clicks "I authorize this application" on the authorization server's login and consent page.
-
Authorization Server Response: The user is redirected back to your application at
http://localhost:8000/callback
with thecode
andstate
parameters.
5. Handle Authorization Response
In your /callback
endpoint, extract the code
and state
from the query parameters.
6. Exchange Authorization Code for Tokens
Make a POST request to the token endpoint to exchange the authorization code for access and refresh tokens.
Token Endpoint:
https://auth.janebunn.website/realms/janesweather/protocol/openid-connect/token
Example Token Request:curl -X POST "https://auth.janebunn.website/realms/janesweather/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "code=AUTHORIZATION_CODE" \
-d "redirect_uri=http://localhost:8000/callback"
Replace:
-
YOUR_CLIENT_ID
with your actual client id.
-
YOUR_CLIENT_SECRET
with your actual client secret. -
AUTHORIZATION_CODE
with the code received from the authorization response.
7. Receive Access and Refresh Tokens
The response will be in JSON format and contain:
-
access_token
-
refresh_token
-
expires_in
-
refresh_expires_in
-
token_type
-
Other OpenID Connect tokens if applicable
Example Response:
"access_token": "ACCESS_TOKEN",
"refresh_token": "REFRESH_TOKEN",
"expires_in": 300,
"refresh_expires_in": 1800,
"token_type": "Bearer",
"id_token": "ID_TOKEN",
"not-before-policy": 0,
"session_state": "SESSION_STATE",
"scope": "openid profile email"
8. Store Tokens for Long-Term Use
Securely store the access_token
and refresh_token
for long-term use.
9. Access Protected Resources
Use the access_token
to access protected resources by including it in the Authorization
header.
Example API Request:
curl -X GET "https://api.janebunn.website/forecast/ecmwf.0p1?lat=-37.840935&lng=144.946457&pid=ChIJ90260rVG1moRkM" \ -H "Authorization: Bearer ACCESS_TOKEN"
Replace ACCESS_TOKEN
with your actual access token.
10. Refresh the Access Token
When the access_token
expires, use the refresh_token
to obtain a new access_token
.
Refresh Token Request:
curl -X POST "https://auth.janebunn.website/realms/janesweather/protocol/openid-connect/token"
-H "Content-Type: application/x-www-form-urlencoded"
-d "grant_type=refresh_token"
-d "client_id=YOUR_CLIENT_ID"
-d "client_secret=YOUR_CLIENT_SECRET"
-d "refresh_token=REFRESH_TOKEN"
Replace:
-
YOUR_CLIENT_ID
with your actual client id. -
YOUR_CLIENT_SECRET
with your actual client secret. -
REFRESH_TOKEN
with your stored refresh token.
11. Revoke Tokens (Logout)
To revoke the refresh token when a user decides to uninstall or disconnect your app.
Revocation Endpoint:
https://auth.janebunn.website/realms/janesweather/protocol/openid-connect/logout
Logout Request:
curl -X POST "https://auth.janebunn.website/realms/janesweather/protocol/openid-connect/logout"
-H "Content-Type: application/x-www-form-urlencoded"
-d "client_id=YOUR_CLIENT_ID"
-d "client_secret=YOUR_CLIENT_SECRET"
-d "refresh_token=REFRESH_TOKEN"
Note: After revoking the token, remove it from your storage.
Long-Term Token StorageCopied!
Importance of Long-Term Storage
Storing tokens long-term allows your application to maintain access to user resources without requiring the user to re-authenticate frequently. This is essential for providing seamless user experiences, such as background data synchronization, notifications, or any functionality that requires ongoing access.
Best Practices for Secure Storage
-
Secure Databases: Use databases with robust security features.
-
Encryption: Encrypt tokens before storing them to prevent unauthorized access.
-
Access Controls: Implement strict access controls to limit who and what can access the tokens.
-
Regular Audits: Monitor access patterns and audit logs regularly.
-
Token Lifecycle Management: Keep track of token expiry and refresh them proactively.
-
Key Management: Securely manage encryption keys, preferably using a Key Management Service (KMS).
Token Revocation Handling
-
User-Initiated Revocation: Provide users with an option to revoke access (e.g., "Uninstall" or "Disconnect" the app).
-
Revoke Tokens: Use the revocation endpoint to invalidate tokens.
Implementation GuidelinesCopied!
Database Storage Strategies
1. Use a Secure Database
-
Recommendations: Use databases like PostgreSQL, MySQL, or secure NoSQL databases.
-
Encryption at Rest: Enable database encryption features to protect data on disk.
-
Backups: Ensure that backups are also encrypted and securely stored.
2. Token Storage Schema
Store tokens in a table associated with the user’s account.
Example Table Structure:
Column |
Type |
Description |
---|---|---|
user_id |
VARCHAR |
Identifier for the user |
access_token |
TEXT |
Encrypted access token |
refresh_token |
TEXT |
Encrypted refresh token |
access_token_expiry |
TIMESTAMP |
Access token expiration time |
refresh_token_expiry |
TIMESTAMP |
Refresh token expiration time |
scopes |
VARCHAR |
Scopes associated with the tokens |
created_at |
TIMESTAMP |
Timestamp when tokens were stored |
updated_at |
TIMESTAMP |
Timestamp when tokens were last updated |
Encryption and Key Management
1. Encrypt Tokens
-
Symmetric Encryption: Use strong algorithms like AES-256.
-
Encryption Libraries: Utilize well-established libraries (e.g., OpenSSL, libsodium).
2. Secure Key Storage
-
Key Management Services (KMS): Use services like AWS KMS, Azure Key Vault, or Google Cloud KMS.
-
Key Rotation: Implement key rotation policies.
-
Access Controls: Restrict access to encryption keys to essential services and personnel.
Access Control and Monitoring
1. Implement Least Privilege
-
Database Users: Create database users with minimal required permissions.
-
Application Access: Ensure that only the necessary parts of your application can access the tokens.
2. Monitoring and Logging
-
Audit Logs: Keep detailed logs of access and modifications to token data.
-
Anomaly Detection: Set up alerts for unusual access patterns or failed access attempts.
3. Secure Application Code
-
Input Validation: Sanitize all inputs to prevent SQL injection and other injection attacks.
-
Secure Coding Practices: Follow best practices like those outlined in the OWASP Top Ten.
ConclusionCopied!
By integrating the OAuth 2.0 Authorization Code Flow using the provided URLs and endpoints, and securely storing tokens for long-term use, your application can provide a seamless and secure user experience. Proper token management ensures that users remain authenticated over extended periods without frequent re-authorization, enhancing usability while maintaining security.
Key Takeaways:
-
User Consent: Users authorize your application once, and you maintain access until they revoke it.
-
Secure Storage: Long-term token storage must be handled with robust security measures to protect user data.
-
Token Lifecycle: Proactively manage token expiry and refresh cycles to ensure uninterrupted access.
-
Revocation Handling: Implement mechanisms for users to revoke access and handle token invalidation accordingly.