OAuthSession class final
A class that manages OAuth 2.0 session information with DPoP (Demonstrating Proof of Possession) support.
This class implements OAuth 2.0 token management with DPoP extension as specified in RFC 9449.
It maintains both standard OAuth token attributes and DPoP-specific components required for proof-of-possession token binding.
Token Components
- Bearer credentials (access and refresh tokens)
- Token metadata (type, scope, expiration)
- Subject identifier for token binding
DPoP Components
- Cryptographic key pair (Base64URL encoded)
The DPoP nonce is intentionally not stored on the session: it is a
short-lived, per-origin value cached separately (see DPoPNonceCache),
so a session can be shared across the authorization server and PDS
origins without nonce ping-pong.
This session is self-contained: it also carries the authorization server
issuer that minted it and the account's pds origin, so an
OAuthClient can refresh or revoke it without re-resolving the identity.
The implementation follows the OAuth 2.0 DPoP security considerations:
- Key material isolation
- Separate storage of sensitive credentials
Security Warning
This object contains highly sensitive secrets: the DPoP private key (dpopPrivateKey) as well as the access and refresh tokens. Anyone in possession of these values can impersonate the authenticated user. Never log this object, and only persist it (e.g. via toJson) into encrypted or otherwise access-controlled storage such as the platform keychain/keystore.
Example:
final session = OAuthSession(
accessToken: 'opaque-access-token...',
refreshToken: 'opaque-refresh-token...',
tokenType: 'DPoP',
scope: 'atproto transition:generic',
expiresAt: DateTime.now().add(Duration(hours: 1)),
sub: 'did:plc:abc',
issuer: 'https://bsky.social',
pds: 'https://pds.example',
clientId: 'https://client.example/client-metadata.json',
dpopPublicKey: 'eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2...',
dpopPrivateKey: 'eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2...',
);
Constructors
- OAuthSession({required String accessToken, String? refreshToken, String tokenType = 'DPoP', required String scope, DateTime? expiresAt, required String sub, required String issuer, required String pds, required String clientId, required String dpopPublicKey, required String dpopPrivateKey})
-
OAuthSession.fromJson(Map<
String, dynamic> json) -
factory
-
OAuthSession.fromLegacyJson(Map<
String, dynamic> json, {required String issuer, required String pds}) -
Restores a session serialized by atproto_oauth <= 0.4.x. Those payloads
used
public_key/private_key, carried a now-obsoletedpop_nonce(discarded — nonces are cached per origin), and lackedissuer/pds, which the caller must supply.factory
Properties
- accessToken → String
-
final
- clientId → String
-
final
- dpopPrivateKey → String
-
final
- dpopPublicKey → String
-
final
- expiresAt → DateTime?
-
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- issuer → String
-
The authorization server issuer that minted this session.
final
- pds → String
-
The account's PDS origin (
https://host[:port]).final - refreshToken → String?
-
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- scope → String
-
final
- sub → String
-
final
- tokenType → String
-
final
Methods
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toJson(
) → Map< String, dynamic> -
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited