AshAtproto.XRPC.OAuthClient (ash_atproto v1.0.0)

Copy Markdown

OAuth client for making authenticated XRPC requests to AT Protocol servers.

The client contains an Ash resource that uses the AshAtproto.UserResource extension to store sessions to make requests. As a result, it will only work for users that have gone through an OAuth flow; see AshAuthentication.Strategy, for an existing method of doing that through AshAuthentication.

The entire OAuth session lifecycle is handled transparently, with the access token being refreshed automatically as required.

The client's state can change if the token is refreshed, so make sure you update the client if the value is returned and you plan to reuse it.

Usage

# Create from a resource
user_resource = Ash.read_one!(MyApp.Accounts.User, authorize?: false)
{:ok, client} = AshAtproto.XRPC.OAuthClient.new(user_resource)

# Make XRPC requests
{:ok, response, client} =
  Atex.XRPC.get(client, "com.atproto.repo.listRecords",
    params: [repo: user.handle, collection: "app.bsky.graph.follow"]
  )

Summary

Functions

Make a GET request to an XRPC endpoint.

Create a new OAuthClient from an user resource. The resource must be using AshAuthentication.Strategy, otherwise the client will crash when it tries to access secrets. A strategy struct can be passed directly, if needed, avoiding the crash.

Make a POST request to an XRPC endpoint.

Ask the client's OAuth server for a new set of auth tokens.

Types

t()

@type t() :: %AshAtproto.XRPC.OAuthClient{
  resource: Ash.Resource.t(),
  strategy: AshAtproto.Auth.t()
}

Functions

get(client, resource, opts \\ [])

Make a GET request to an XRPC endpoint.

See Atex.XRPC.get/3 for details.

new(resource)

@spec new(Ash.Resource.t()) :: {:ok, t()} | {:error, atom()}

Create a new OAuthClient from an user resource. The resource must be using AshAuthentication.Strategy, otherwise the client will crash when it tries to access secrets. A strategy struct can be passed directly, if needed, avoiding the crash.

Examples

iex> user_resource = Ash.read_one!(MyApp.Accounts.User, authorize?: false)
%MyApp.Accounts.User{
  did: "did:plc:dgzvruva4jbzqbta335jtvoz",
  handle: "lekkice.moe",
  ...
}
iex> {:ok, client} = AshAtproto.XRPC.OAuthClient.new(user_resource)
{:ok,
 %AshAtproto.XRPC.OAuthClient{
   resource: %MyApp.Accounts.User{
     did: "did:plc:dgzvruva4jbzqbta335jtvoz",
     handle: "lekkice.moe",
     ...
   }
 }}

new(resource, strategy)

@spec new(Ash.Resource.t(), AshAtproto.Auth.t()) :: {:ok, t()} | {:error, atom()}

post(client, resource, opts \\ [])

Make a POST request to an XRPC endpoint.

See Atex.XRPC.post/3 for details.

refresh(client)

@spec refresh(client :: t()) :: {:ok, t()} | {:error, any()}

Ask the client's OAuth server for a new set of auth tokens.

Refreshes the tokens, persists the new tokens, then returns the updated resource.

You shouldn't need to call this manually for the most part, the client does its best to refresh automatically when it needs to.

This function acquires a lock on the session to prevent concurrent refresh attempts.