Current section
Files
Jump to
Current section
Files
src/atproto/oauth/resource.gleam
//// DPoP-authenticated resource requests: wraps a transport so every request
//// carries `Authorization: DPoP <token>` and a proof bound to its method, URL,
//// and access-token hash, with the server-nonce retry. Token refresh is the
//// caller's job (it owns session persistence); this module only signs.
////
//// A thin sync wrapper over the effect kernel in `atproto_core/oauth/resource`:
//// it computes the access-token hash (`ath`) once and runs the per-request
//// signing effect against the base client.
import atproto/oauth/runner
import atproto/xrpc.{type Client}
import atproto_core/oauth/resource as core
import atproto_core/xrpc as core_xrpc
import gleam/bit_array
import gleam/crypto
import gleam/result
import gose
/// A client that signs every request against the given DPoP-bound access token.
pub fn client(
base: Client,
access_token access_token: String,
dpop_key dpop_key: gose.Key(String),
) -> Client {
let ath =
base64url(crypto.hash(crypto.Sha256, bit_array.from_string(access_token)))
xrpc.Client(send: fn(req) {
runner.run(core.send(req, access_token:, ath:), base, dpop_key)
|> result.map_error(core_xrpc.Other)
})
}
fn base64url(bits: BitArray) -> String {
bit_array.base64_url_encode(bits, False)
}