# `Stevedore.Auth`
[🔗](https://github.com/oshlabs/stevedore/blob/v0.2.0/lib/stevedore/auth.ex#L1)

Registry credentials and the bearer-token challenge/exchange flow.

Registries advertise how to authenticate via a `401` response carrying a
`WWW-Authenticate: Bearer realm=…,service=…,scope=…` header. `parse_challenge/1` reads that
header; `token/3` exchanges it (plus optional credentials) for a bearer token at the realm's
token endpoint. Credentials can be supplied directly or loaded from `~/.docker/config.json`.

Spec: [Docker token authentication](https://distribution.github.io/distribution/spec/auth/token/)
and the distribution-spec authentication section.

# `challenge`

```elixir
@type challenge() :: %{
  realm: String.t(),
  service: String.t() | nil,
  scope: String.t() | nil
}
```

# `creds`

```elixir
@type creds() :: :anonymous | {:basic, user :: String.t(), pass :: String.t()}
```

# `from_docker_config`

```elixir
@spec from_docker_config(Path.t() | nil) ::
  {:ok, %{optional(String.t()) =&gt; creds()}} | {:error, term()}
```

Loads credentials from a Docker config file (default `~/.docker/config.json`), returning a map
of registry host to `t:creds/0`. A missing file yields an empty map.

# `parse_challenge`

```elixir
@spec parse_challenge(String.t()) :: {:ok, challenge()} | {:error, :unsupported}
```

Parses a `WWW-Authenticate` header value. Only the `Bearer` scheme is supported; `Basic` and
unknown schemes return `{:error, :unsupported}`.

## Examples

    iex> Stevedore.Auth.parse_challenge(~s(Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/alpine:pull"))
    {:ok, %{realm: "https://auth.docker.io/token", service: "registry.docker.io", scope: "repository:library/alpine:pull"}}

    iex> Stevedore.Auth.parse_challenge("Basic realm=\"registry\"")
    {:error, :unsupported}

# `token`

```elixir
@spec token(challenge(), creds(), keyword()) ::
  {:ok, String.t()} | {:error, Stevedore.Auth.Error.t()}
```

Exchanges a parsed `challenge` for a bearer token, sending `creds` as HTTP Basic to the token
endpoint when they are not `:anonymous`.

`opts` may carry `:req_options` (a keyword merged into the `Req` request, e.g. an `:adapter`)
for testing.

---

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