# `Immich.API.OAuth`

OAuth authentication flow for the Immich API.

This module provides the two-step authorization code flow used by Immich:

1. `authorize/2` starts the flow and returns a remote login URL.
2. `callback/3` completes the flow after the browser redirect and builds
   an `Immich.API.Session`.

The module is intentionally stateless. Callers are responsible for storing
the returned OAuth context between steps.

## Shared options

Most functions accept `shared_opts`:

- `:base_url` (required) - Immich server URL (for example
  `"https://demo.immich.app"`)
- `:client` (optional) - HTTP client module implementing
  `Immich.API.Client.Behaviour` (defaults to `Immich.API.Client`)

## Usage

```elixir
alias Immich.Api.OAuth

opts = [base_url: "https://demo.immich.app"]

# Step 1: Start flow
{:ok, login_url, oauth_context} =
  OAuth.authorize("http://localhost:55555/oauth-callback", opts)

# Open login_url in browser, then receive callback URL in your app.
callback_url = "http://localhost:55555/oauth-callback?code=...&state=..."

# Step 2: Complete flow
{:ok, session} = OAuth.callback(callback_url, oauth_context, opts)

# session.access_token can now be used for authenticated API calls.
```

## Error handling

Functions return `{:error, reason}` tuples for API-level failures, including
transport/authentication errors from the configured client and unexpected
successful payloads (`{:unexpected_response, payload}`).

# `base_url`

```elixir
@type base_url() :: String.t()
```

Immich server base URL without the trailing /api (for example, https://demo.immich.app)

# `callback_uri`

```elixir
@type callback_uri() :: String.t()
```

Callback URI received after OAuth login.

# `login_url`

```elixir
@type login_url() :: String.t()
```

Login URL returned by authorize.

# `oauth_context`

```elixir
@type oauth_context() :: %{pkce: Immich.API.PKCE.t()}
```

# `oauth_error`

```elixir
@type oauth_error() :: Immich.API.Client.api_error() | {:unexpected_response, term()}
```

Error tuple returned by OAuth functions.

# `redirect_uri`

```elixir
@type redirect_uri() :: String.t()
```

Redirect URI sent to the authorize endpoint.

# `shared_opts`

```elixir
@type shared_opts() :: [base_url: base_url(), client: Immich.API.Client.t()]
```

Shared options for OAuth requests.

# `authorize`

```elixir
@spec authorize(redirect_uri(), shared_opts()) ::
  {:ok, login_url(), oauth_context()} | {:error, oauth_error()}
```

Starts OAuth login

This function starts the OAuth login flow and returns the remote login URL
authorization context that needs to be passed to callback/3.

# `callback`

```elixir
@spec callback(callback_uri(), oauth_context(), shared_opts()) ::
  {:ok, Immich.API.Session.t()} | {:error, oauth_error()}
```

Completes OAuth callback exchange and returns an authenticated session.

This function should be called after the user has been redirected back to
your application from the OAuth provider.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
