Skip to main content

Crate rustlavel_oauth_provider

Crate rustlavel_oauth_provider 

Source
Expand description

rustlavel-oauth-provider: be an OAuth 2.1 authorization server.

This is Laravel Passport’s job — letting other applications sign users in through yours. The mirror half, signing your users in through somebody else’s, is rustlavel-oauth, whose types this crate speaks so both ends agree on the wire format by construction.

ⓘ
use rustlavel_oauth_provider::prelude::*;

let clients = MemoryClientStore::new().with(
    Client::confidential("checkout", &secret)
        .named("Checkout")
        .redirect_uri("https://checkout.test/oauth/callback")
        .scopes(Scopes::of(["orders.read", "orders.write"])),
);

App::new()?
    .plugin(OAuthProvider::new(
        AuthorizationServer::new(clients).issued_by("https://accounts.example.com"),
    ))
    .serve()
    .await

That mounts six routes: /oauth/authorize (GET and POST), /oauth/token, /oauth/revoke, /oauth/introspect, and the RFC 8414 discovery document at /.well-known/oauth-authorization-server. Guarding your own API with the tokens it issues is RequireToken.

§What this server will not do

It is OAuth 2.1, not 2.0 with the dangerous parts left in:

  • PKCE is required, for every client, and only S256 is accepted. plain is refused, and an absent code_challenge_method is an error rather than a default — RFC 7636 §4.3 defaults it to plain, which would let a client turn PKCE off by omitting a parameter.
  • The implicit flow is gone. response_type=token returns an access token in a URL fragment, where it lands in browser history and in every script on the page.
  • The password grant is gone. It asks the user to type their password into somebody else’s application, cannot carry a second factor, and hands the client a credential that works everywhere.
  • Redirect URIs are matched byte for byte against the registered set. No prefixes, no wildcards. redirect explains what each relaxation lets through.
  • A leaked credential takes its family down with it. A replayed authorisation code and a reused refresh token both revoke every token descended from that authorisation, because either one means two parties hold a credential that was issued to one.

§Where the data lives

Four traits — ClientStore, CodeStore, TokenStore, ConsentStore — each with two implementations: an in-memory one for tests and a development server, and a table-backed one in database behind the db feature. Deploy the second. A restart empties the first, and an empty store answers “unknown token” to everything.

The database is optional rather than absent: an application with no database compiles none of it, and one with its own tables implements the traits instead. See store for the reasoning, and for the two operations that must be atomic whichever you use.

§Cryptography

SHA-256, from sha2, is the only primitive here: every credential is stored as a digest and compared in constant time, and PKCE’s S256 is the same hash. Nothing else is invented. There is no JWT option and no JWKS: an access token here is opaque so that revoking it revokes it, which a self-contained signed token cannot offer.

Re-exports§

pub use client::Client;
pub use client::ClientStore;
pub use client::MemoryClientStore;
pub use client::generate_secret;
pub use clock::Clock;
pub use code::AuthorizationCode;
pub use code::CodeStore;
pub use code::Consumption;
pub use code::MemoryCodeStore;
pub use consent::ConsentStore;
pub use consent::Grant;
pub use consent::MemoryConsentStore;
pub use plugin::OAuthProvider;
pub use resource::BearerExt;
pub use resource::RequireToken;
pub use resource::TokenClaims;
pub use server::AuthorizationServer;
pub use server::Settings;
pub use store::StoreFuture;
pub use token::AccessToken;
pub use token::MemoryTokenStore;
pub use token::RefreshToken;
pub use token::TokenStore;

Modules§

client
Registered clients: who is allowed to ask this server for a token.
clock
The one place this crate asks what time it is.
code
Authorisation codes: single-use, short-lived, and bound to everything.
consent
What a user has already agreed to.
endpoints
The HTTP surface: five routes, and the pieces they share.
page
The two pages this server renders itself: the consent screen, and the error page for a request that must not be redirected anywhere.
plugin
Turning the provider on.
prelude
What a main.rs or a controller imports to use this package.
redirect
Redirect URI matching, which is where authorisation servers get breached.
resource
The other side of the exchange: guarding your own routes with a token this server issued.
server
The authorisation server: the stores, the settings, and the few operations that more than one endpoint needs.
store
What the four stores share, and how a credential is kept at rest.
token
Access and refresh tokens, and the family that ties them together.

Structs§

OAuthError
The protocol vocabulary, re-exported so an application needs one import. An OAuth error: a code, and an optional description for a human.
Scopes
The protocol vocabulary, re-exported so an application needs one import. A set of scopes, kept sorted so one set always renders identically.
TokenResponse
The protocol vocabulary, re-exported so an application needs one import. What a token endpoint returns on success.

Enums§

ChallengeMethod
The protocol vocabulary, re-exported so an application needs one import. How the challenge was derived from the verifier.
Error
Every failure the framework itself can produce.
OAuthErrorCode
The protocol vocabulary, re-exported so an application needs one import. The error codes defined by RFC 6749 §4.1.2.1 (authorisation endpoint) and §5.2 (token endpoint), plus the two RFC 6750 codes a resource server needs.

Type Aliases§

Result
The framework-wide result type.