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-obsolete dpop_nonce (discarded — nonces are cached per origin), and lacked issuer/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