A simple, reusable authentication crate supporting both Rocket backend API and Yew frontend authentication components with multi-user support. https://crates.io/crates/prisma_auth
Find a file
2025-10-15 09:05:08 +02:00
example Update toml and 2024 edition 2025-10-15 08:47:43 +02:00
src Improve documentation 2025-09-24 18:09:17 +02:00
tests Fix tests implementation 2025-09-23 19:46:17 +02:00
.gitignore Initial commit 2025-09-15 20:49:27 +02:00
Cargo.lock Fix minor README details 2025-10-15 09:05:08 +02:00
Cargo.toml Fix minor README details 2025-10-15 09:05:08 +02:00
LICENSE Initial commit 2025-09-15 20:49:27 +02:00
README.md Fix minor README details 2025-10-15 09:05:08 +02:00
test.sh Fix tests implementation 2025-09-23 19:46:17 +02:00

Prisma Auth

A simple, reusable authentication crate supporting both Rocket backend API and Yew frontend authentication components with multi-user support.

Features

  • Backend Support: Rocket-based authentication with JWT tokens
  • Multi-User Authentication: Support for multiple users with roles and permissions
  • Secure Password Hashing: Uses Argon2 for password hashing
  • Role-Based Access Control: Dynamic roles and permissions system
  • Frontend Support: Yew components for login and authentication guards
  • Token Management: Automatic token storage, validation, and expiration
  • Modular Design: Use backend, frontend, or both features as needed

(back to top)

Usage

Add to your Cargo.toml:

[dependencies]
# For backend (Rocket API)
prisma_auth = { version = "0.2.1", features = ["rocket_backend"] }

# For frontend (Yew WASM)
prisma_auth = { version = "0.2.1", features = ["yew_frontend"] }

# For both
prisma_auth = { version = "0.2.1", features = ["rocket_backend", "yew_frontend"] }

(back to top)

Backend Usage (Rocket)

Basic Setup

use rocket::State;
use prisma_auth::multi_user::{AuthService, MultiUserTokenStore, MultiUserAuthGuard, multi_user_login_handler, register_handler};
use prisma_auth::storage::InMemoryStorage;
use prisma_auth::{LoginRequest, RegisterRequest, TokenResponse};

#[rocket::post("/login", format = "json", data = "<body>")]
pub fn login(
    body: Json<LoginRequest>,
    token_store: &State<MultiUserTokenStore>,
    auth_service: &State<AuthService<InMemoryStorage>>,
) -> Result<Json<TokenResponse>, Status> {
    multi_user_login_handler(body, token_store, auth_service)
}

#[rocket::post("/register", format = "json", data = "<body>")]
pub fn register(
    body: Json<RegisterRequest>,
    auth_service: &State<AuthService<InMemoryStorage>>,
    admin: MultiUserAuthGuard,
) -> Result<Json<User>, Status> {
    register_handler(body, auth_service, admin)
}

#[rocket::get("/protected")]
pub fn protected_route(auth: MultiUserAuthGuard) -> String {
    format!("Hello, {}! Your role: {}", auth.username, auth.role)
}

#[rocket::get("/admin-only")]
pub fn admin_only(auth: MultiUserAuthGuard) -> Result<&'static str, Status> {
    if auth.has_permission("admin") || auth.is_admin() {
        Ok("Admin area accessed!")
    } else {
        Err(Status::Forbidden)
    }
}

#[launch]
fn rocket() -> _ {
    let storage = InMemoryStorage::new().with_default_roles();
    let auth_service = AuthService::new(storage);

    rocket::build()
        .manage(MultiUserTokenStore::new())
        .manage(auth_service)
        .mount("/api", routes![login, register, protected_route, admin_only])
}

Environment Variables

  • ADMIN_PASSWORD: Required. The initial admin password for authentication
  • TOKEN_TTL_SECONDS: Optional. Token expiration time in seconds (default: 600)

(back to top)

Frontend Usage (Yew)

Login Component

use yew::prelude::*;
use prisma_auth::frontend::{MultiUserLoginComponent, UserInfo};

#[function_component(Login)]
pub fn login() -> Html {
    let on_success = Callback::from(|user_info: UserInfo| {
        web_sys::console::log_1(&format!("Login successful! User: {}, Role: {}",
            user_info.username, user_info.role).into());
    });

    html! {
        <MultiUserLoginComponent
            api_base_url={"http://localhost:8000/api".to_string()}
            on_success={on_success}
            title={"My App".to_string()}
            subtitle={"Please login".to_string()}
            show_username={true} // Enable multi-user mode
        />
    }
}

Basic Authentication Guard

use yew::prelude::*;
use prisma_auth::frontend::AuthGuardComponent;

#[function_component(ProtectedPage)]
pub fn protected_page() -> Html {
    let fallback = html! {
        <div>{"Please login to access this page"}</div>
    };

    html! {
        <AuthGuardComponent fallback={Some(fallback)}>
            <div>{"This content is only visible to authenticated users"}</div>
        </AuthGuardComponent>
    }
}

Permission-Based Guards

use yew::prelude::*;
use prisma_auth::frontend::{PermissionGuardComponent, use_multi_user_auth};

#[function_component(AdminPage)]
pub fn admin_page() -> Html {
    let (user_info, _refresh) = use_multi_user_auth();

    html! {
        <PermissionGuardComponent required_permission="admin_panel".to_string()>
            <div>
                <h1>{"Admin Panel"}</h1>
                { if let Some(user) = user_info {
                    html! { <p>{format!("Welcome, {}!", user.username)}</p> }
                } else {
                    html! { <p>{"Loading user info..."}</p> }
                }}
            </div>
        </PermissionGuardComponent>
    }
}

Manual Token Management

use prisma_auth::frontend::{get_stored_token, store_token, logout, is_authenticated};

if is_authenticated() {
    // User has a valid token stored
}

// Get the current token
if let Some(token) = get_stored_token() {
    // Use token for API requests
}

store_token("your-jwt-token").unwrap();

// Logout (remove stored token)
logout().unwrap();

Making Authenticated API Requests

use prisma_auth::frontend::{make_authenticated_request, make_request_with_token};

// Using stored token automatically
let response = make_authenticated_request(
    "GET",
    "/protected-endpoint",
    None,
    "http://localhost:8000/api"
).await?;

// Using a specific token
let response = make_request_with_token(
    "POST",
    "/endpoint",
    Some(serde_json::json!({"data": "value"})),
    Some("your-token"),
    "http://localhost:8000/api"
).await?;

User Management

use prisma_auth::frontend::{get_user_info, logout_multi_user, use_multi_user_auth};

#[function_component(UserProfile)]
pub fn user_profile() -> Html {
    let (user_info, refresh) = use_multi_user_auth();

    let logout_click = {
        let refresh = refresh.clone();
        Callback::from(move |_| {
            let _ = logout_multi_user();
            refresh.emit(());
        })
    };

    html! {
        <div>
            { if let Some(user) = user_info {
                html! {
                    <div>
                        <h2>{"User Profile"}</h2>
                        <p>{format!("Username: {}", user.username)}</p>
                        <p>{format!("Role: {}", user.role)}</p>
                        <button onclick={logout_click}>{"Logout"}</button>
                    </div>
                }
            } else {
                html! { <p>{"Not logged in"}</p> }
            }}
        </div>
    }
}

(back to top)

Role and Permission Management

Creating Custom Roles

use prisma_auth::{Role, storage::InMemoryStorage, multi_user::AuthService};

let storage = InMemoryStorage::new();
let auth_service = AuthService::new(storage);

// Create custom roles
let editor_role = Role {
    name: "editor".to_string(),
    permissions: vec!["read".to_string(), "write".to_string(), "edit_posts".to_string()],
    description: Some("Can read, write, and edit posts".to_string()),
};

let moderator_role = Role {
    name: "moderator".to_string(),
    permissions: vec!["read".to_string(), "moderate_comments".to_string(), "ban_users".to_string()],
    description: Some("Can moderate content and manage users".to_string()),
};

auth_service.manage_role(editor_role)?;
auth_service.manage_role(moderator_role)?;

User Registration with Roles

use prisma_auth::RegisterRequest;

let register_request = RegisterRequest {
    username: "alice".to_string(),
    password: "secure_password123".to_string(),
    role: Some("editor".to_string()),
};

let user = auth_service.register_user(register_request)?;

(back to top)

Contributing

Contributions are welcome! Please fork the repository, make your changes, and open a pull request.

  1. Fork the Project on Forgejo
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

License

Distributed under the European Union Public License v1.2. See LICENSE for more information.

(back to top)

Contact

Aitor Astorga Saez de Vicuña - a.astorga.sdv@protonmail.com

Project Link: https://git.prisma.moe/aichan/prisma_auth

(back to top)

Acknowledgments

Thanks to these amazing projects and technologies!

  • Rust Yew - A modern Rust framework for creating multi-threaded front-end web apps with WebAssembly
  • Rocket - A web framework for Rust that makes it simple to write fast, secure web applications
  • WebAssembly - A binary instruction format for a stack-based virtual machine

(back to top)