-
Notifications
You must be signed in to change notification settings - Fork 4
RustifyAuth Wiki
This project is an authentication and authorization server library based on OAuth 2.0 and OAuth 2.1, written in Rust. The goal is to provide developers with an extensible, secure, and scalable solution for managing OAuth flows with advanced security features.
RustifyAuth is a modular OAuth 2.0 and OAuth 2.1-compliant authentication library that enables developers to implement authorization flows such as Authorization Code with PKCE, Client Credentials, Refresh Token, and more. The library is designed for production environments with a focus on performance and security.
- Rust (latest stable version)
- Cargo (Rust's package manager)
- OpenSSL (for handling encryption)
You can install Rust from the official website: Install Rust.
To add RustifyAuth to your project, include it in your Cargo.toml file:
[dependencies]
rustify-auth = "0.1"Then, run cargo build to install the necessary dependencies.
Setting Up the Project After installation, you can start by configuring your environment, token store, and setting up routes. Refer to the Configuration section for more details.
OAuth 2.0 & OAuth 2.1 Support: Full compliance with RFC 6749 (OAuth 2.0) and draft specifications of OAuth 2.1. PKCE Support: Proof Key for Code Exchange, providing enhanced security for public clients. Token Management: In-memory and pluggable token stores for managing access and refresh tokens. Rate Limiting: Protect endpoints from abuse. Advanced Security: Quantum-resistant signing algorithms (Dilithium, Falcon), MFA support, and CSRF protection. JWT Handling: JSON Web Token (JWT) generation, signing, and verification. Pluggable Architecture: Easily replace storage backends or extend with new features. Actix Web Integration: Built-in integration with Actix Web for easy route management. Supported Grant Types RustifyAuth supports multiple grant types to comply with OAuth 2.0/2.1 specifications. The currently supported grant types include:
Authorization Code with PKCE Client Credentials Refresh Token Device Flow Extension Grants In the future, we plan to add additional flows based on community needs.
Environment Variables
RustifyAuth uses a .env file to handle sensitive data like secrets and tokens. Example .env file:
JWT_SECRET=mysecret
TOKEN_EXPIRATION=3600
DATABASE_URL=postgres://user:password@localhost/dbname
Token Store Configuration By default, RustifyAuth uses an in-memory token store. For production, it is recommended to use a persistent store (e.g., Redis, PostgreSQL). Here's an example of setting up an in-memory token store:
let token_store = InMemoryTokenStore::new();
JWT Configuration Ensure you configure your JWT with appropriate signing algorithms and keys. You can use RSA/ECC or even quantum-resistant algorithms such as Dilithium or Falcon for advanced use cases.
Authorization Endpoint (Authorization Code Flow)
Route: /authorize Method: GET Description: Initiates the OAuth Authorization Code flow. Token Endpoint
Route: /token Method: POST Description: Exchanges authorization codes for access or refresh tokens. Revocation Endpoint
Route: /revoke Method: POST Description: Revokes tokens (both access and refresh tokens). Introspection Endpoint
Route: /introspect Method: POST Description: Validates access tokens. Refer to the full API Documentation for more details on endpoint usage.
Here’s a quick example to set up an OAuth2 Authorization Code Flow with PKCE:
use rustify_auth::token_store::InMemoryTokenStore;
use rustify_auth::endpoints::{authorize, token};
fn main() {
let token_store = InMemoryTokenStore::new();
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(token_store.clone()))
.route("/authorize", web::get().to(authorize))
.route("/token", web::post().to(token))
})
.bind("127.0.0.1:8080")?
.run()
.await;
}
For more detailed examples and advanced usage, visit the Examples page.
RustifyAuth comes with a comprehensive suite of tests to ensure the functionality of various components.
Running Tests To run the tests, use the following command:
cargo test
The Device Authorization Flow allows devices (e.g., smart TVs or IoT devices) to request access to a user’s account without requiring the user to enter credentials directly on the device. Instead, users are provided with a user_code that they enter on a verification page using a separate device, such as a mobile phone or computer.
This guide walks you through the entire device authorization process, including the steps required to request a device_code, how users can authorize the device, and how the client application can obtain an access token after the authorization is complete.
The flow consists of the following key steps:
- Device Requests Authorization:
- The device sends a POST request to the /device_authorize endpoint with the client ID and requested scopes (if applicable). This request initiates the authorization process and returns a
device_codeanduser_code.
- User Authorizes the Device:
The user is prompted to visit a verification page (e.g., https://yourdomain.com/device) and enter the provided user_code to authorize the device. The server marks the corresponding device code as authorized.
- Device Polls for Token:
The device periodically sends a request to the /device_token endpoint with the device_code to check if the user has authorized the device. Once authorized, the server responds with an access token.
This endpoint is used by devices to initiate the authorization process and request a device_code and user_code.
-
URL:
/device_authorize -
Method:
POST -
Request Body:
{
"client_id": "your_client_id",
"scope": "read write"
}
Response:
{
"device_code": "generated_device_code",
"user_code": "generated_user_code",
"verification_uri": "https://yourdomain.com/device",
"expires_in": 600,
"interval": 5
}
- Explanation:
device_code: A unique code for the device to use when polling for the token.
user_code: The code that the user will enter on the verification page.
verification_uri: The URL where the user needs to enter the user_code.
expires_in: The time (in seconds) after which the device_code expires.
interval: The interval (in seconds) that the device should wait between polling requests.
The verification page is where the user enters the user_code to authorize the device. After the user enters the user_code, the server marks the corresponding device_code as authorized.
-
User Input: User enters the user_code received from the device.
-
Backend Process: The server checks the user_code, and if valid, authorizes the device code in the system.
After the device has obtained a device_code, it periodically sends a request to the /device_token endpoint to check if the user has authorized the device.
-
URL:
/device_token -
Method:
POST -
Request Body:
{
"client_id": "your_client_id",
"device_code": "your_device_code"
}
- Response (Before Authorization):
{
"error": "authorization_pending"
}
- Response (After Authorization):
{
"access_token": "generated_access_token",
"token_type": "Bearer",
"expires_in": 3600
}
*** Explanation**:
- access_token: The token that can be used to access protected resources.
- token_type: The type of token (usually Bearer).
- expires_in: The duration (in seconds) that the token is valid for.
*** Error Responses:**
-
authorization_pending: The user has not yet authorized the device. -
expired_token: Thedevice_codehas expired. -
invalid_request: The request contains an invalid or non-existentdevice_code.
The device sends a request to /device_authorize to initiate the authorization process. The server responds with a device_code and user_code.
POST /device_authorize
{
"client_id": "your_client_id",
"scope": "read write"
}
Response:
{
"device_code": "device_code_123",
"user_code": "user_code_456",
"verification_uri": "https://yourdomain.com/device",
"expires_in": 600,
"interval": 5
}
The user visits https://yourdomain.com/device on a separate device (e.g., their phone) and enters the user_code to authorize the device.
The device periodically sends a request to /device_token with the device_code. If the user has not yet authorized the device, the response will contain the error authorization_pending.
POST /device_token
{
"client_id": "your_client_id",
"device_code": "device_code_123"
}
Response (Before Authorization):
{
"error": "authorization_pending"
}
Once the user authorizes the device, the device receives the access token:
Response (After Authorization):
{
"access_token": "access_token_789",
"token_type": "Bearer",
"expires_in": 3600
}
Now that the device has an access_token, it can use this token to access protected resources by sending it in the Authorization header.
GET /protected_resource
Authorization: Bearer access_token_789
You can configure the following environment variables to customize the behavior of the Device Authorization Flow:
-
VERIFICATION_URI: The URL where users enter the user_code. (Default:
https://yourdomain.com/device) - EXPIRES_IN: The expiration time (in seconds) for device codes. (Default: 600)
- INTERVAL: The interval (in seconds) that the device should wait between polling for the token. (Default: 5)
Example .env File
VERIFICATION_URI=https://yourdomain.com/device
EXPIRES_IN=600
INTERVAL=5
The following errors might occur during the device authorization flow:
- authorization_pending: The user has not yet authorized the device.
- expired_token: The device_code has expired.
-
invalid_request: The request contains an invalid or non-existent
device_code.
- Rate Limiting: Ensure that the
/device_tokenpolling endpoint is rate-limited to prevent abuse. - Authorization Time: Devices should respect the
expires_inandintervalvalues provided in theDeviceAuthorizationResponse. - Scopes and Permissions: Ensure that tokens are generated with the correct scopes based on the client's request.
Welcome to the Authorization Grant Type Documentation for the RustifyAuth library! This page provides a comprehensive guide to implementing the Authorization Code Flow with PKCE (Proof Key for Code Exchange) in RustifyAuth, ensuring a secure and robust authorization process for developers.
The Authorization Code Flow with PKCE in RustifyAuth is designed to enable secure access delegation, commonly used by both confidential and public clients. PKCE adds an extra layer of security to ensure that authorization codes cannot be intercepted or misused.
This guide walks through each step of the Authorization Grant Type, allowing developers to securely implement the flow in their applications.
Authorization Request
- Initiate Authorization The client (application) begins the authorization request by providing the following parameters to the authorization endpoint:
-
response_type: Must be set to "code" for authorization code flow. -
client_id: The unique identifier of the client application. -
redirect_uri: The URI where the authorization code will be sent after the user authorizes access. -
scope: Optional, specifies the level of access requested (e.g., "read write"). -
state: Optional, recommended for preventing CSRF attacks. -
code_challengeandcode_challenge_method: PKCE parameters, required for public clients to enhance security.
- Endpoint Example
GET /authorize?response_type=code&client_id=your_client_id&redirect_uri=https://yourapp.com/callback&scope=read&state=xyz&code_challenge=abcd123&code_challenge_method=S256
PKCE Challenge The PKCE mechanism requires generating a code challenge and code verifier.
- Generate Code Challenge and Verifier
- Verifier: Random string, 43-128 characters.
- Challenge: SHA-256 hash of the verifier (Base64URL encoded).
- Supported Methods
-
S256: Recommended for security. -
plain: Supported, but less secure.
Authorization Code Generation Upon receiving the authorization request, RustifyAuth performs the following:
- Validate Client and PKCE: Ensures
client_idis valid,redirect_uriis authorized, and PKCE parameters are correct. - Generate Authorization Code: A unique, time-limited code is generated.
- Redirect to Client: RustifyAuth redirects the user back to the specified
redirect_uriwith the authorization code.
Token Exchange To obtain an access token:
- Token Request
The client sends the authorization code,
client_id,redirect_uri, andcode_verifier(PKCE verifier) to the token endpoint.
POST /token
{
"client_id": "your_client_id",
"code": "authorization_code",
"redirect_uri": "https://yourapp.com/callback",
"code_verifier": "code_verifier_string"
}
- Token Validation and Exchange
RustifyAuth validates the code, PKCE verifier, and expiration. Upon success, it returns an access token and refresh token to the client.
Token Response Structure The token response contains the following attributes:
- access_token: The token used to access resources.
- refresh_token: The token used to obtain a new access token when the current one expires.
- token_type: Usually "Bearer".
- expires_in: Time in seconds for the token’s validity.
- scope: The granted scope(s).
Error Handling RustifyAuth handles various error cases in the Authorization Grant Flow. Below are common errors and suggested handling:
- Invalid Code: Returned if the provided authorization code is invalid.
- Expired Code: Returned if the authorization code has expired.
- Invalid PKCE: Returned if the PKCE challenge validation fails.
- Token Generation Error: Occurs if there’s an issue generating tokens.
Security Recommendations To ensure a secure implementation:
- Use PKCE: Especially for public clients to prevent authorization code interception.
- Scope Validation: Ensure scopes are checked against authorized scopes.
- Session Management: Use secure session cookies or tokens with HttpOnly and Secure flags.
- Rate Limiting: Limit repeated authorization attempts to prevent brute-force attacks.
Example Code Below is sample code for implementing the Authorization Grant Flow using RustifyAuth.
Authorization Request:
let auth_request = AuthorizationRequest {
response_type: "code".to_string(),
client_id: "your_client_id".to_string(),
redirect_uri: "https://yourapp.com/callback".to_string(),
scope: Some("read write".to_string()),
state: Some("xyz".to_string()),
code_challenge: Some("base64url_encoded_sha256_challenge".to_string()),
code_challenge_method: Some("S256".to_string()),
};
Token Exchange:
let token_request = TokenExchangeRequest {
client_id: "your_client_id".to_string(),
code: "authorization_code".to_string(),
redirect_uri: "https://yourapp.com/callback".to_string(),
code_verifier: "original_code_verifier".to_string(),
};
let token_response = rustify_auth.exchange_code_for_token(token_request);
Advanced Use Cases
- TOTP Authentication: For additional security, combine the Authorization Code Flow with TOTP for multifactor authentication.
- Introspection and Revocation: Enable introspection and revocation endpoints to manage and verify token validity.