Skip to content

Commit f5ef74c

Browse files
committed
docs: update readmes to reflect implementation
1 parent 22832f5 commit f5ef74c

10 files changed

Lines changed: 564 additions & 54 deletions

File tree

authly-actix/README.md

Lines changed: 114 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
Actix-web integration for [authly-rs](https://github.com/marcjazz/authly-rs).
44

5-
This crate provides Actix-web specific helpers and utilities to integrate the `authly` authentication framework into Actix applications.
5+
This crate provides Actix-web specific extractors and utilities to integrate the `authly` authentication framework into Actix applications.
66

77
## Features
88

9-
- Actix-web compatible extractors and middleware helpers.
10-
- Easy integration with `authly-flow` for OAuth2 and OIDC.
9+
- **Extractors**: Easily access validated sessions or JWT claims in your request handlers.
10+
- **OAuth2 Helpers**: Streamlined functions for initiating login, handling callbacks, and logging out.
11+
- **Session Management**: Integration with `authly-session` for server-side session storage.
1112

1213
## Usage
1314

@@ -16,6 +17,116 @@ Add this to your `Cargo.toml`:
1617
```toml
1718
[dependencies]
1819
authly-actix = "0.1.0"
20+
authly-session = "0.1.0"
21+
authly-token = "0.1.0"
22+
actix-web = "4"
23+
```
24+
25+
### Extractors
26+
27+
#### `AuthSession`
28+
29+
Extracts a validated session from a cookie. Requires `Arc<dyn SessionStore>` and `SessionConfig` to be registered in `app_data`.
30+
31+
```rust
32+
use authly_actix::AuthSession;
33+
use actix_web::{get, HttpResponse};
34+
35+
#[get("/profile")]
36+
async fn profile(auth: AuthSession) -> HttpResponse {
37+
let session = auth.0;
38+
HttpResponse::Ok().json(session.identity)
39+
}
40+
```
41+
42+
#### `AuthToken`
43+
44+
Extracts and validates a JWT from the `Authorization: Bearer <token>` header. Requires `Arc<TokenManager>` to be registered in `app_data`.
45+
46+
```rust
47+
use authly_actix::AuthToken;
48+
use actix_web::{get, HttpResponse};
49+
50+
#[get("/api/data")]
51+
async fn protected_api(token: AuthToken) -> HttpResponse {
52+
let claims = token.0;
53+
HttpResponse::Ok().json(claims)
54+
}
55+
```
56+
57+
### OAuth2 Helpers
58+
59+
The crate provides helpers to manage the OAuth2 flow lifecycle.
60+
61+
```rust
62+
use authly_actix::{initiate_oauth_login, handle_oauth_callback, logout, SessionConfig, OAuthCallbackParams};
63+
use actix_web::{web, HttpRequest, HttpResponse, get};
64+
use std::sync::Arc;
65+
66+
// 1. Initiate Login
67+
#[get("/login")]
68+
async fn login(flow: web::Data<OAuth2Flow>, config: web::Data<SessionConfig>) -> HttpResponse {
69+
initiate_oauth_login(&flow, &config, &["user:email"])
70+
}
71+
72+
// 2. Handle Callback
73+
#[get("/callback")]
74+
async fn callback(
75+
req: HttpRequest,
76+
params: web::Query<OAuthCallbackParams>,
77+
flow: web::Data<OAuth2Flow>,
78+
store: web::Data<Arc<dyn SessionStore>>,
79+
config: web::Data<SessionConfig>,
80+
) -> Result<HttpResponse, actix_web::Error> {
81+
handle_oauth_callback(
82+
req,
83+
&flow,
84+
params.into_inner(),
85+
store.get_ref().clone(),
86+
config.get_ref().clone(),
87+
"/dashboard"
88+
).await
89+
}
90+
91+
// 3. Logout
92+
#[get("/logout")]
93+
async fn sign_out(
94+
req: HttpRequest,
95+
store: web::Data<Arc<dyn SessionStore>>,
96+
config: web::Data<SessionConfig>,
97+
) -> Result<HttpResponse, actix_web::Error> {
98+
logout(req, store.get_ref().clone(), config.get_ref().clone(), "/").await
99+
}
100+
```
101+
102+
### Setup
103+
104+
To use the extractors and helpers, you must configure your Actix app with the necessary data:
105+
106+
```rust
107+
use actix_web::{web, App, HttpServer};
108+
use authly_actix::SessionConfig;
109+
use authly_session::MemoryStore;
110+
use authly_token::TokenManager;
111+
use std::sync::Arc;
112+
113+
#[actix_web::main]
114+
async fn main() -> std::io::Result<()> {
115+
let session_store: Arc<dyn SessionStore> = Arc::new(MemoryStore::new());
116+
let token_manager = Arc::new(TokenManager::new("your-secret".to_string()));
117+
let session_config = SessionConfig::default();
118+
119+
HttpServer::new(move || {
120+
App::new()
121+
.app_data(web::Data::new(session_store.clone()))
122+
.app_data(web::Data::new(token_manager.clone()))
123+
.app_data(web::Data::new(session_config.clone()))
124+
// ... routes
125+
})
126+
.bind("127.0.0.1:8080")?
127+
.run()
128+
.await
129+
}
19130
```
20131

21132
## Part of authly-rs

authly-axum/README.md

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,16 @@ This crate provides Axum-specific extractors and helpers to easily integrate the
66

77
## Features
88

9-
- Extractors for `AuthSession`.
10-
- Helpers for initiating OAuth logins and handling callbacks.
11-
- Session configuration with secure cookie defaults.
9+
- **Extractors**:
10+
- `AuthSession`: Extracts a validated session from cookies.
11+
- `AuthToken`: Extracts and validates a JWT from the `Authorization: Bearer` header.
12+
- **OAuth Helpers**:
13+
- `initiate_oauth_login`: Generates authorization URLs and handles CSRF protection.
14+
- `handle_oauth_callback`: Finalizes OAuth login and creates a server-side session.
15+
- `handle_oauth_callback_jwt`: Finalizes OAuth login and returns a JWT.
16+
- **Session Management**:
17+
- `logout`: Clears the session cookie and removes it from the store.
18+
- `SessionConfig`: Customizable session settings (cookie name, secure, http_only, etc.).
1219

1320
## Usage
1421

@@ -17,21 +24,62 @@ Add this to your `Cargo.toml`:
1724
```toml
1825
[dependencies]
1926
authly-axum = "0.1.0"
27+
tower-cookies = "0.10" # Required for session support
2028
```
2129

22-
### Example
30+
### Example: Session-based Authentication
2331

2432
```rust
25-
use axum::{routing::get, Router};
26-
use authly_axum::{AuthSession, HasSessionStore};
33+
use axum::{routing::get, Router, extract::State};
34+
use authly_axum::{AuthSession, SessionConfig, initiate_oauth_login, handle_oauth_callback};
35+
use authly_session::SessionStore;
36+
use tower_cookies::CookieManagerLayer;
37+
use std::sync::Arc;
38+
39+
#[derive(Clone)]
40+
struct AppState {
41+
session_store: Arc<dyn SessionStore>,
42+
session_config: SessionConfig,
43+
// ... other state like OAuth flows
44+
}
45+
46+
// Implement FromRef for the extractors to work
47+
impl axum::extract::FromRef<AppState> for Arc<dyn SessionStore> {
48+
fn from_ref(state: &AppState) -> Self {
49+
state.session_store.clone()
50+
}
51+
}
52+
53+
impl axum::extract::FromRef<AppState> for SessionConfig {
54+
fn from_ref(state: &AppState) -> Self {
55+
state.session_config.clone()
56+
}
57+
}
2758

2859
async fn protected_handler(AuthSession(session): AuthSession) -> String {
2960
format!("Welcome back, {}!", session.identity.username.unwrap_or_default())
3061
}
3162

32-
fn app() -> Router {
33-
// ... setup state with SessionStore and OAuthProvider
34-
Router::new().route("/protected", get(protected_handler))
63+
fn app(state: AppState) -> Router {
64+
Router::new()
65+
.route("/protected", get(protected_handler))
66+
// The CookieManagerLayer is required for AuthSession and OAuth helpers
67+
.layer(CookieManagerLayer::new())
68+
.with_state(state)
69+
}
70+
```
71+
72+
### Example: JWT-based Authentication
73+
74+
```rust
75+
use authly_axum::AuthToken;
76+
use authly_token::TokenManager;
77+
use std::sync::Arc;
78+
79+
// Ensure Arc<TokenManager> is available in your State via FromRef
80+
81+
async fn api_handler(AuthToken(claims): AuthToken) -> String {
82+
format!("Hello user with ID: {}", claims.sub)
3583
}
3684
```
3785

authly-core/README.md

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ This crate provides the foundational types and traits used across the `authly` f
66

77
## Features
88

9-
- `Identity` structure for unified user information.
10-
- `OAuthProvider` trait for implementing new OAuth2 providers.
11-
- `CredentialsProvider` trait for password-based auth.
12-
- `UserMapper` trait for mapping identities to local database users.
13-
- Standard `AuthError` types.
9+
- `Identity` structure for unified user information across different providers.
10+
- `OAuthToken` structure for standard OAuth2 token responses.
11+
- `OAuthProvider` trait for implementing OAuth2-compatible authentication providers.
12+
- `CredentialsProvider` trait for password-based or custom credential authentication.
13+
- `UserMapper` trait for mapping provider identities to local application users.
14+
- `pkce` module for Proof Key for Code Exchange support.
15+
- Standard `AuthError` enum for consistent error handling.
1416

1517
## Usage
1618

@@ -21,6 +23,60 @@ Add this to your `Cargo.toml`:
2123
authly-core = "0.1.0"
2224
```
2325

26+
### Core Traits
27+
28+
#### OAuthProvider
29+
30+
The `OAuthProvider` trait defines the interface for OAuth2 providers. It includes methods for generating authorization URLs and exchanging codes for identities.
31+
32+
```rust
33+
#[async_trait]
34+
pub trait OAuthProvider: Send + Sync {
35+
fn get_authorization_url(
36+
&self,
37+
state: &str,
38+
scopes: &[&str],
39+
code_challenge: Option<&str>,
40+
) -> String;
41+
42+
async fn exchange_code_for_identity(
43+
&self,
44+
code: &str,
45+
code_verifier: Option<&str>,
46+
) -> Result<(Identity, OAuthToken), AuthError>;
47+
48+
// Optional methods for token management
49+
async fn refresh_token(&self, refresh_token: &str) -> Result<OAuthToken, AuthError>;
50+
async fn revoke_token(&self, token: &str) -> Result<(), AuthError>;
51+
}
52+
```
53+
54+
#### CredentialsProvider
55+
56+
The `CredentialsProvider` trait is used for non-OAuth authentication methods, such as email/password.
57+
58+
```rust
59+
#[async_trait]
60+
pub trait CredentialsProvider: Send + Sync {
61+
type Credentials;
62+
63+
async fn authenticate(&self, creds: Self::Credentials) -> Result<Identity, AuthError>;
64+
}
65+
```
66+
67+
#### UserMapper
68+
69+
The `UserMapper` trait allows you to bridge the gap between a provider's `Identity` and your application's local user model.
70+
71+
```rust
72+
#[async_trait]
73+
pub trait UserMapper: Send + Sync {
74+
type LocalUser: Send + Sync;
75+
76+
async fn map_user(&self, identity: &Identity) -> Result<Self::LocalUser, AuthError>;
77+
}
78+
```
79+
2480
## Part of authly-rs
2581

2682
This crate is part of the [authly-rs](https://github.com/marcjazz/authly-rs) workspace. `authly` is a modular, framework-agnostic authentication orchestration system for Rust.

authly-flow/README.md

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
High-level authentication flows for [authly-rs](https://github.com/marcjazz/authly-rs).
44

5-
This crate orchestrates authentication flows such as OAuth2 and credentials-based auth, providing a high-level API that is independent of web frameworks.
5+
This crate orchestrates authentication flows such as OAuth2, Device Flow, Client Credentials, and direct credentials-based auth, providing a high-level API that is independent of web frameworks.
66

77
## Features
88

99
- `OAuth2Flow`: Orchestrates the Authorization Code flow (initiation and finalization).
10+
- `DeviceFlow`: Orchestrates the Device Authorization Flow (RFC 8628).
11+
- `ClientCredentialsFlow`: Orchestrates the Client Credentials Flow (RFC 6749 Section 4.4).
1012
- `CredentialsFlow`: Orchestrates direct credential-based authentication.
1113
- Support for `UserMapper` to integrate with local user databases.
1214

@@ -19,7 +21,7 @@ Add this to your `Cargo.toml`:
1921
authly-flow = "0.1.0"
2022
```
2123

22-
### Example: OAuth2 Flow initiation
24+
### Example: OAuth2 Flow
2325

2426
```rust
2527
use authly_flow::OAuth2Flow;
@@ -29,8 +31,55 @@ use authly_providers_github::GitHubProvider;
2931
let provider = GitHubProvider::new(client_id, client_secret, callback_url);
3032
let flow = OAuth2Flow::new(provider);
3133

32-
// Generate authorization URL
33-
let (auth_url, _csrf_state) = flow.initiate_auth(None);
34+
// 1. Initiate login: Generate authorization URL and CSRF state
35+
let (auth_url, csrf_state) = flow.initiate_login(&["user:email"], None);
36+
37+
// ... redirect user to auth_url, then receive code and state in callback ...
38+
39+
// 2. Finalize login: Exchange code for identity and tokens
40+
let (identity, token, local_user) = flow.finalize_login(
41+
&code,
42+
&received_state,
43+
&expected_state,
44+
None // PKCE verifier
45+
).await?;
46+
```
47+
48+
### Example: Device Flow
49+
50+
```rust
51+
use authly_flow::DeviceFlow;
52+
53+
let flow = DeviceFlow::new(client_id, device_auth_url, token_url);
54+
55+
// 1. Initiate device authorization
56+
let resp = flow.initiate_device_authorization(&["read", "write"]).await?;
57+
58+
println!("Go to {} and enter code: {}", resp.verification_uri, resp.user_code);
59+
60+
// 2. Poll for token
61+
let token = flow.poll_for_token(&resp.device_code, resp.interval).await?;
62+
```
63+
64+
### Example: Client Credentials Flow
65+
66+
```rust
67+
use authly_flow::ClientCredentialsFlow;
68+
69+
let flow = ClientCredentialsFlow::new(client_id, client_secret, token_url);
70+
71+
// Obtain an access token
72+
let token = flow.get_token(Some(&["api:read"])).await?;
73+
```
74+
75+
### Example: Credentials Flow
76+
77+
```rust
78+
use authly_flow::CredentialsFlow;
79+
// Assuming a provider that implements CredentialsProvider
80+
let flow = CredentialsFlow::new(my_credentials_provider);
81+
82+
let (identity, local_user) = flow.authenticate(my_credentials).await?;
3483
```
3584

3685
## Part of authly-rs

0 commit comments

Comments
 (0)