Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Auth In The API Contract

RAS puts auth requirements next to the endpoint or method declaration:

UNAUTHORIZED health(()) -> HealthStatus,
OPTIONAL_AUTH feed(()) -> Feed,
WITH_PERMISSIONS(["user"]) get_profile(()) -> UserProfile,
WITH_PERMISSIONS(["admin"] | ["owner", "editor"]) update_project(UpdateProject) -> Project,

This is deliberate. When auth is part of the API definition, generated code can enforce it consistently and generated API documents can expose it to clients.

Shared Runtime Model

All service macros integrate with ras-auth-core:

use ras_auth_core::{AuthFuture, AuthProvider, AuthenticatedUser};

struct MyAuthProvider;

impl AuthProvider for MyAuthProvider {
    fn authenticate(&self, token: String) -> AuthFuture<'_> {
        Box::pin(async move {
            // Validate a JWT, API key, session token, or other credential.
            todo!("return an AuthenticatedUser or AuthError")
        })
    }
}

AuthProvider::authenticate turns a credential into an AuthenticatedUser. The default check_permissions implementation requires that the user has every permission listed in the group, and providers may override that method for custom policy.

Auth Syntax

UNAUTHORIZED means the generated server does not require a credential for the operation.

OPTIONAL_AUTH means the operation is public, but opportunistically identified. The route is never rejected for auth reasons; instead the handler receives a ras_auth_core::Caller as its first argument:

pub enum Caller {
    Anonymous,
    Authenticated(AuthenticatedUser),
}

Resolution is fully lenient: a missing credential, an invalid or expired token, a missing auth provider, or a cookie credential that fails CSRF on an unsafe method (POST/PUT/PATCH/DELETE) all resolve to Caller::Anonymous — a forged or stale credential simply executes as the public path. A valid credential resolves to Caller::Authenticated(user). No permission check is performed. Reach for it on “public, but richer when signed in” endpoints (per-document ACLs, personalization, author previews). The file_service! macro surfaces the same optional caller through FileRequestContext rather than a Caller parameter.

WITH_PERMISSIONS(["a", "b"]) means the generated server requires a valid credential and a permission group containing both a and b.

Groups use OR logic between groups and AND logic within a group:

WITH_PERMISSIONS(["admin"] | ["moderator", "editor"])

That allows either admin, or both moderator and editor.

An empty group is the authenticated-only form:

WITH_PERMISSIONS([])

It requires a valid user but no specific permission.

The same syntax is accepted by JSON-RPC, REST, file, and bidirectional JSON-RPC service macros.

What Gets Documented

When OpenRPC or OpenAPI generation is enabled, protected operations include authentication metadata. REST and file services expose bearer auth security requirements in OpenAPI, and JSON-RPC methods expose x-authentication. Permission names are also emitted as extension metadata so explorer UIs and client-generation workflows can show what a call requires. x-permissions contains a flattened compatibility list, while x-permission-groups preserves the real OR/AND grouping.

OPTIONAL_AUTH operations advertise an optional security requirement: REST and file services emit security: [{}, { "bearerAuth": [] }] (anonymous is acceptable, and a bearer token is honoured), and JSON-RPC methods emit x-authentication with "required": false.