Packages
atproto_browser
0.1.0
A browser-native atproto OAuth + XRPC client for Gleam: WebCrypto DPoP, PKCE, and async transport, for building a public-client SPA with no server-side session custody.
Current section
Files
Jump to
Current section
Files
src/atproto/browser/oauth/tokens.gleam
//// Async mirror of `atproto/oauth/tokens.gleam`: token endpoint calls —
//// exchange an authorization code for DPoP-bound tokens, refresh them, and
//// best-effort revocation. A thin async wrapper over the shared effect kernel
//// in `atproto_core/oauth/tokens`; the `Tokens` type is
//// re-exported from there.
import atproto/browser/dpop.{type DpopKey}
import atproto/browser/oauth/flow.{type Flow}
import atproto/browser/oauth/runner
import atproto/browser/xrpc.{type Client}
import atproto_core/oauth/tokens as core
import gleam/javascript/promise.{type Promise}
pub type Tokens =
core.Tokens
pub fn exchange_code(
client: Client,
flow flow: Flow,
code code: String,
redirect_uri redirect_uri: String,
extra_form extra_form: List(#(String, String)),
) -> Promise(Result(Tokens, String)) {
runner.run(
core.exchange_code(
token_endpoint: flow.token_endpoint,
code:,
redirect_uri:,
client_id: flow.client_id,
pkce_verifier: flow.pkce_verifier,
extra_form:,
),
client,
flow.dpop_key,
)
}
pub fn refresh(
client: Client,
token_endpoint token_endpoint: String,
refresh_token refresh_token: String,
client_id client_id: String,
dpop_key dpop_key: DpopKey,
extra_form extra_form: List(#(String, String)),
) -> Promise(Result(Tokens, String)) {
runner.run(
core.refresh(token_endpoint:, refresh_token:, client_id:, extra_form:),
client,
dpop_key,
)
}
/// Best-effort refresh-token revocation at logout: discover the AS revocation
/// endpoint from the issuer and revoke. Failures are ignored (the caller
/// clears its local session regardless).
pub fn revoke(
client: Client,
issuer issuer: String,
refresh_token refresh_token: String,
client_id client_id: String,
dpop_key dpop_key: DpopKey,
extra_form extra_form: List(#(String, String)),
) -> Promise(Nil) {
runner.run(
core.revoke(issuer:, refresh_token:, client_id:, extra_form:),
client,
dpop_key,
)
}