Skip to content

RustifyAuth Wiki

Mehrnoush edited this page Oct 25, 2024 · 10 revisions

Welcome to the 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.

Overview

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.


Getting Started

Prerequisites

  • Rust (latest stable version)
  • Cargo (Rust's package manager)
  • OpenSSL (for handling encryption)

You can install Rust from the official website: Install Rust.

Installation

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.


Features

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.


Configuration

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.


Endpoints

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.


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.


Testing

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



Device Authorization Flow

Overview

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.

Steps in the Flow

The flow consists of the following key steps:

  1. 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_code and user_code.
  1. 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.

  1. 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.

Endpoints

1. Device Authorization Endpoint (/device_authorize)

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.

2. Verification Page

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.

  • URL: https://yourdomain.com/device

  • 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.

3. Device Token Polling Endpoint (/device_token)

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: The device_code has expired.
  • invalid_request: The request contains an invalid or non-existent device_code.

Example Flow

1. Device Requests Authorization

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
}

2. User Authorizes the Device

The user visits https://yourdomain.com/device on a separate device (e.g., their phone) and enters the user_code to authorize the device.

3. Device Polls for Token

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
}

4. Accessing Protected Resources

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

Configuration

Environment Variables

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

Error Handling

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.

Security Considerations

  1. Rate Limiting: Ensure that the /device_token polling endpoint is rate-limited to prevent abuse.
  2. Authorization Time: Devices should respect the expires_in and interval values provided in the DeviceAuthorizationResponse.
  3. Scopes and Permissions: Ensure that tokens are generated with the correct scopes based on the client's request.


Authorization Grant Type Documentation for RustifyAuth****

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.

Overview

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.

Step-by-Step Guide

Authorization Request

  1. 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_challenge and code_challenge_method: PKCE parameters, required for public clients to enhance security.
  1. 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.

  1. Generate Code Challenge and Verifier
  • Verifier: Random string, 43-128 characters.
  • Challenge: SHA-256 hash of the verifier (Base64URL encoded).
  1. Supported Methods
  • S256: Recommended for security.
  • plain: Supported, but less secure.

Authorization Code Generation Upon receiving the authorization request, RustifyAuth performs the following:

  1. Validate Client and PKCE: Ensures client_id is valid, redirect_uri is authorized, and PKCE parameters are correct.
  2. Generate Authorization Code: A unique, time-limited code is generated.
  3. Redirect to Client: RustifyAuth redirects the user back to the specified redirect_uri with the authorization code.

Token Exchange To obtain an access token:

  1. Token Request The client sends the authorization code, client_id, redirect_uri, and code_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"
}
  1. 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

  1. TOTP Authentication: For additional security, combine the Authorization Code Flow with TOTP for multifactor authentication.
  2. Introspection and Revocation: Enable introspection and revocation endpoints to manage and verify token validity.

Clone this wiki locally