Better Auth in Rust

Sessions

Session lifecycle, transport, refresh behavior, and session-management endpoints.

The SessionManagementPlugin provides endpoints for querying, listing, and revoking sessions. Sessions are created automatically during sign-up, sign-in, passkey authentication, and successful 2FA completion.

Setup

These examples assume you've already defined AppAuthSchema. If you want a complete setup from entity definitions through Axum mounting, start with the Axum integration guide.

use better_auth::plugins::SessionManagementPlugin;

let auth = BetterAuth::<AppAuthSchema>::new(config)
    .store(store)
    .plugin(SessionManagementPlugin::new())
    .build()
    .await?;

Plugin Options

OptionTypeDefaultDescription
enable_session_listingbooltrueAllow GET /list-sessions
enable_session_revocationbooltrueAllow revocation endpoints
require_authenticationbooltrueRequire a valid session for plugin endpoints

Opaque Session Tokens

For the v1 release surface, Better Auth uses opaque session tokens stored in the database and transported through:

Authorization: Bearer session_abc123...
Cookie: better-auth.session_token=session_abc123...

JWTs are a separate optional surface documented in phase 13. They are not how the phase 0-12 session endpoints authenticate requests.

Endpoints

MethodPathDescription
GET/get-sessionReturn the current session and user
POST/sign-outRevoke the current session and clear cookies
GET/list-sessionsList all active sessions for the current user
POST/revoke-sessionRevoke one specific session by token
POST/revoke-sessionsRevoke all sessions for the current user
POST/revoke-other-sessionsRevoke every session except the current one

Session Lifecycle

  1. A session is created after successful authentication.
  2. The opaque token and session metadata are stored in the database.
  3. The token is returned to the client and usually set as a cookie.
  4. Authenticated requests resolve the token back to the stored session.
  5. Expired or revoked sessions stop authenticating requests.

Refresh Behavior

Session refresh is controlled by SessionConfig:

use better_auth::AuthConfig;
use better_auth::config::SameSite;
use chrono::Duration;

let mut config = AuthConfig::new("secret...")
    .base_url("https://auth.example.com");
config.session.expires_in = Duration::days(7);
config.session.update_age = Some(Duration::days(1));
config.session.disable_session_refresh = false;
config.session.fresh_age = Some(Duration::minutes(10));
config.session.cookie_name = "better-auth.session_token".to_string();
config.session.cookie_secure = true;
config.session.cookie_http_only = true;
config.session.cookie_same_site = SameSite::Lax;
  • update_age = Some(duration): refresh only when the session is older than that duration.
  • update_age = None: refresh on every access.
  • disable_session_refresh = true: never refresh automatically.
  • fresh_age: optional window for treating a session as "fresh" for sensitive actions.

Using Sessions in Axum Handlers

With the axum feature, use the CurrentSession extractor to access the authenticated user directly in your handler:

use axum::Json;
use better_auth::integrations::axum::CurrentSession;
use better_auth::prelude::{AuthSession, AuthUser};

async fn profile(session: CurrentSession<AppAuthSchema>) -> Json<serde_json::Value> {
    Json(serde_json::json!({
        "user_id": session.user.id(),
        "session_token": session.session.token(),
    }))
}

Use OptionalSession<AppAuthSchema> for routes that should work for both authenticated and anonymous users.

Two-Factor Interaction

When 2FA is enabled, sign-in verifies the primary credential first and then pauses on a pending verification flow. A full session is only created after verify-totp, verify-otp, or verify-backup-code succeeds.

Security Notes

  • Session tokens are generated with OsRng.
  • Cookie transport should normally keep Secure, HttpOnly, and SameSite enabled.
  • Session records can retain audit metadata such as IP address and user-agent.
  • Users can hold multiple sessions across devices and revoke them selectively.

On this page