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
S256is accepted.plainis refused, and an absentcode_challenge_methodis an error rather than a default — RFC 7636 §4.3 defaults it toplain, which would let a client turn PKCE off by omitting a parameter. - The implicit flow is gone.
response_type=tokenreturns 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 an in-memory implementation for tests and
development. There is deliberately no dependency on rustlavel-db; see
[store] for why an application backs these with its own tables.
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.