Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/its-danny/tower-surf
🌊 A stateless CSRF middleware for tower.
https://github.com/its-danny/tower-surf
Last synced: about 1 month ago
JSON representation
🌊 A stateless CSRF middleware for tower.
- Host: GitHub
- URL: https://github.com/its-danny/tower-surf
- Owner: its-danny
- License: apache-2.0
- Created: 2024-08-18T20:53:35.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2024-08-20T15:52:18.000Z (4 months ago)
- Last Synced: 2024-10-27T22:10:52.414Z (about 2 months ago)
- Language: Rust
- Size: 78.1 KB
- Stars: 29
- Watchers: 0
- Forks: 1
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
🌊 tower-surf
A stateless CSRF middleware for [tower][crate-tower].
[![Crates](https://img.shields.io/crates/v/tower-surf.svg)](https://crates.io/crates/tower-surf)
![MSRV](https://img.shields.io/crates/msrv/tower-surf)
[![Docs](https://docs.rs/tower-surf/badge.svg)](https://docs.rs/tower-surf)
![CI](https://github.com/its-danny/tower-surf/actions/workflows/ci.yml/badge.svg)## 🏄♂️ Overview
This crate uses the [Double Submit Cookie Pattern][owasp-double-submit] to mitigate CSRF.
### How it works
- **Secret key**: You provide a **secret key** used to sign CSRF tokens. This secret is secured by [secstr][crate-secstr] and only
in memory as plaintext during the signing and validating processes.
For more information on managing your secret key, see [OWASP's Cryptographic Storage Cheat Sheet][owasp-cryptographic-storage]).
- **Token creation**:
- We generate a **message** by combining a unique **session identifier** with a cryptographically secure **random value** (using the [`rand`][crate-rand] crate).
- We then create an **signature** using the **secret key** and the **message**.
- The token is formed by concatenating the **signature** and the **message**.
- **Token storage**:
- The server sends the token to the client in two ways:
- As a cookie (handled by us).
- In the header of subsequent requests (handled by you).
- **Token validation**:
- For each incoming request that would mutate state:
- We extract the token from the request headers.
- We split the token into the **signature** and the **message**.
- We recalculate the **signature** using the **secret key** and compare them.
- If the **signature** is valid and the token matches the value stored in the cookie, the request is allowed to proceed.### Cookies
By default, the cookies are set to `HTTPOnly`, `SameSite: Strict`, and `Secure`.
## 📦 Install
```toml
[dependencies]
tower-surf = "0.3.0"
```## 🗝️ Usage
### With [`axum`][crate-axum]
```rust
use std::net::SocketAddr;use axum::{routing::get, Router};
use http::StatusCode;
use tower_surf::{Surf, Token};#[tokio::main]
async fn main() {
let app = Router::new()
.route("/login", get(login)).route("/logout", get(logout))
.layer(Surf::new("secret-key").secure(false));let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();axum::serve(listener, app.into_make_service())
.await
.unwrap();
}async fn login(token: Token) -> Result {
token.set("unique-session-id").map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;Ok(StatusCode::OK)
}async fn logout(token: Token) -> StatusCode {
token.reset();StatusCode::OK
}
```> [!NOTE]
> See the [examples][examples] for a full example.## 🥰 Thank you
- I read a lot of the [tower-sessions](https://github.com/maxcountryman/tower-sessions) codebase to figure out how to make a tower project.
- The [tokio community](https://discord.com/invite/tokio) answered a lot of silly questions.[crate-axum]: https://github.com/tokio-rs/axum
[crate-rand]: https://github.com/rust-random/rand
[crate-tower]: https://github.com/tower-rs/tower
[crate-secstr]: https://codeberg.org/valpackett/secstr
[examples]: https://github.com/its-danny/tower-surf/tree/main/examples
[owasp-cryptographic-storage]: https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html
[owasp-double-submit]: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#alternative-using-a-double-submit-cookie-pattern