# `HuggingfaceClient.Hub.OAuth`
[🔗](https://github.com/huggingface/huggingface_client/blob/v0.1.0/lib/huggingface_client/hub/oauth.ex#L1)

PKCE OAuth 2.0 login flow for HuggingFace Hub.

Implements the Authorization Code flow with Proof Key for Code Exchange (PKCE)
as required by the HuggingFace OAuth provider.

## Usage

    # Step 1 — build the redirect URL
    {:ok, %{url: url, state: state, nonce: nonce, code_verifier: verifier}} =
      HuggingfaceClient.Hub.OAuth.login_url(client_id: "my-app-id")

    # Redirect the user to `url`, storing state/nonce/verifier in session.

    # Step 2 — after the user is redirected back, exchange the code
    {:ok, %{"access_token" => token}} =
      HuggingfaceClient.Hub.OAuth.handle_redirect(
        code:          params["code"],
        state:         params["state"],
        stored_state:  session["state"],
        nonce:         session["nonce"],
        code_verifier: session["code_verifier"],
        client_id:     "my-app-id"
      )

# `handle_redirect`

```elixir
@spec handle_redirect(keyword()) :: {:ok, map()} | {:error, Exception.t()}
```

Validates the OAuth callback and exchanges the code for tokens.

## Required options

- `:code`          — authorization code from the callback params
- `:state`         — state from the callback params
- `:stored_state`  — state saved in session before redirect
- `:code_verifier` — PKCE verifier saved in session before redirect
- `:client_id`     — same client ID used in `login_url/1`

## Optional options

- `:redirect_uri`, `:hub_url`, `:client_secret`

Returns `{:error, InputError.t()}` on state mismatch or missing code.

# `login_url`

```elixir
@spec login_url(keyword()) ::
  {:ok,
   %{
     url: String.t(),
     state: String.t(),
     nonce: String.t(),
     code_verifier: String.t()
   }}
  | {:error, HuggingfaceClient.Error.InputError.t()}
```

Generates a PKCE authorization URL to start the OAuth login flow.

## Required options

- `:client_id` — your registered OAuth application client ID

## Optional options

- `:redirect_uri` — callback URL (must match what's registered)
- `:scope` — space-separated OAuth scopes (default: `"openid profile"`)
- `:hub_url` — override the HF Hub base URL

## Returns

`{:ok, %{url: binary, state: binary, nonce: binary, code_verifier: binary}}`
or `{:error, InputError.t()}` if `client_id` is missing.

---

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