AshAtproto#
Ash utilities built on top of atex to make integrating with ATProto easier. It includes:
- An Ash extension that provides resource actions and attributes for an user.
- An
AshAuthenticationstrategy to enable the OAuth flow. - AN XRPC client to make requests using an user resource.
Installation#
The package can be installed by adding ash_atproto to your list of dependencies in mix.exs:
def deps do
[
{:ash_atproto, "~> 0.1.0"}
]
end
User resource extension#
This extension modifies your resource to add the following attributes:
:did: an user's DID. This will be used as a primary key.:handle: an user's handle. This is cached for easier access, but it can become stale.:oauth_tokens: a struct with the OAuth response data.
These attributes can be overridden if necessary, and new attributes can be added with no issues.
It also includes the following actions:
:register_with_atproto: upsert used for both registers and sign ins.:refresh: updates the:oauth_tokensattribute.:read:destroy
Example#
defmodule MyApp.Accounts.User do
use Ash.Resource,
otp_app: :my_app,
domain: MyApp.Accounts,
authorizers: [Ash.Policy.Authorizer],
extensions: [AshAuthentication, AshAtproto.Auth, AshAtproto.UserResource],
data_layer: AshPostgres.DataLayer
authentication do
tokens do
enabled? true
require_token_presence_for_authentication? true
token_resource MyApp.Accounts.Token
signing_secret MyApp.Secrets
store_all_tokens? true
end
strategies do
atproto do
registration_enabled? true
base_url MyApp.Secrets
private_key MyApp.Secrets
key_id(MyApp.Secrets)
end
end
end
postgres do
table "users"
repo MyApp.Repo
end
actions do
read :get_by_subject do
description "Get a user by the subject claim in a JWT"
argument :subject, :string, allow_nil?: false
get? true
prepare AshAuthentication.Preparations.FilterBySubject
end
end
policies do
bypass AshAuthentication.Checks.AshAuthenticationInteraction do
authorize_if always()
end
policy always() do
forbid_if always()
end
end
end
AshAuthentication strategy#
A strategy that enables seamless integration with the rest of AshAuthentication. The atproto strategy is standalone, and can be used without the user resource extension (replacing it with AshAuthentication.UserIdentity, for example).
Example#
use Ash.Resource,
extensions: [AshAuthentication, AshAtproto.Auth],
strategies do
atproto do
registration_enabled? true
base_url MyApp.Secrets
private_key MyApp.Secrets
key_id(MyApp.Secrets)
end
end
Configuration values can be passed directly, but using AshAuthentication.Secret is recommended.
OAuth client#
An HTTP API client that follows the XRPC conventions. Will automatically refresh tokens if needed.
Example#
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"]
)
For more details, including lexicon code generation and typed parameters, check the Atex.XRPC module.
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/ash_atproto.