WardrikOAuth (wardrik_oauth v0.1.0-rc.1)

Copy Markdown

OAuth sign-in for WardrikCore agents. Grants are sealed in a WardrikVault.

children = [
  {WardrikVault, name: MyApp.Vault, store: store, keys: keys, grants: {WardrikOAuth, MyApp.OAuth}},
  {WardrikOAuth,
   name: MyApp.OAuth,
   vault: MyApp.Vault,
   store: store,
   page: "https://agents.example.com/oauth",
   on_granted: {MyApp.Agents, :granted, []},
   providers: [github: [issuer: "https://github.com/login/oauth", client_id: id, client_secret: secret]]}
]

Mount WardrikOAuth.Plug at page to finish sign-ins. See WardrikOAuth.Provider for provider options.

A provider's client_secret may be {:secret, name}. It's read from the vault's deployment secrets each time a sign-in needs it, so a new one takes effect at once. See WardrikVault.value/2.

Summary

Functions

Adds the provider name at runtime, on every node.

Returns the URL where principal signs in with the provider name.

Returns a specification to start this module under a supervisor.

Returns the Client ID Metadata Document served at {page}/client.

Finishes a browser sign-in from its callback's query params.

Describes the device sign-in id.

Returns the names of the providers someone can sign in with.

Removes the provider name, added at runtime, and the client registered for it.

Functions

add_provider(oauth, name, opts)

@spec add_provider(atom(), String.t(), keyword()) :: :ok | {:error, String.t()}

Adds the provider name at runtime, on every node.

:ok = WardrikOAuth.add_provider(MyApp.OAuth, "linear", resource: "https://mcp.linear.app/mcp")

Takes the same options as a provider in :providers. The client_secret is sealed in the vault, not kept in the store.

Without a client_id, Wardrik gets one the first time someone signs in:

  1. If the service reads Client ID Metadata Documents and page is https, the client_id is the URL of the document WardrikOAuth.Plug serves.
  2. Otherwise, Wardrik registers itself with the service.

Returns {:error, reason} for invalid options, or a name given in :providers.

authorize(oauth, name, principal)

@spec authorize(atom(), String.t(), WardrikCore.Principal.t()) ::
  {:ok, String.t()} | {:error, term()}

Returns the URL where principal signs in with the provider name.

Starts a sign-in, or returns the URL of the one already under way.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

client_document(oauth)

@spec client_document(atom()) :: map()

Returns the Client ID Metadata Document served at {page}/client.

Its URL is Wardrik's client_id with services that read these documents.

finish(oauth, params)

@spec finish(atom(), map()) :: {:ok, String.t()} | {:error, term()}

Finishes a browser sign-in from its callback's query params.

The params carry "state", and "code" or "error". Returns {:ok, provider} or {:error, reason}, and {:error, :no_such_flow} if the sign-in has ended.

WardrikOAuth.Plug calls this. Call it yourself to handle the callback in your own route.

flow(oauth, id)

@spec flow(atom(), String.t()) :: {:ok, map()} | :error

Describes the device sign-in id.

Returns {:ok, map} with :provider, :principal, :user_code and :verification_uri, or :error if the sign-in has ended.

providers(oauth)

@spec providers(atom()) :: [String.t()]

Returns the names of the providers someone can sign in with.

remove_provider(oauth, name)

@spec remove_provider(atom(), String.t()) :: :ok | {:error, term()}

Removes the provider name, added at runtime, and the client registered for it.

start_link(opts)

@spec start_link(keyword()) :: Supervisor.on_start()

Starts WardrikOAuth.

Options

  • :name - required. The name functions reach it by.
  • :vault - required. The WardrikVault grants are sealed in.
  • :store - required. The WardrikStore for providers added at runtime and registered clients.
  • :page - required. The URL WardrikOAuth.Plug is mounted at, as "https://agents.example.com/oauth".
  • :providers - providers to start with, as a keyword list of name and options. See WardrikOAuth.Provider. [] unless set.
  • :on_granted - {module, function, args} called with the provider's name and the principal, then args, after each grant.
  • :client_name - the name a service shows for a client Wardrik registers. "Wardrik" unless set.
  • :req_options - extra options for every Req request.
  • :check - a function called on each URL before a request is sent. It returns :ok or {:error, reason}. Use one when users add providers by URL. Without it, any https URL, and http on localhost, is reached.