# Autenticación de Registry


Este documento describe el esquema de autenticación de registry:

![v2 registry auth](/reference/api/registry/images/v2-registry-auth.png)

1. Intentar iniciar una operación push/pull con el registry.
2. Si el registry requiere autorización, devolverá una respuesta HTTP `401 Unauthorized` con información sobre cómo autenticarse.
3. El cliente de registry realiza una solicitud al servicio de autorización para obtener un token Bearer.
4. El servicio de autorización devuelve un token Bearer opaco que representa el acceso autorizado del cliente.
5. El cliente reintenta la solicitud original con el token Bearer incrustado en la cabecera `Authorization` de la solicitud.
6. El Registry autoriza al cliente validando el token Bearer y el conjunto de notificaciones (claim set) incrustado en él, e inicia la sesión push/pull como de costumbre.

## Requisitos

- Clientes de registry que puedan comprender y responder a los desafíos (challenges) de autenticación de token devueltos por el servidor de recursos.
- Un servidor de autorización capaz de gestionar los controles de acceso a sus recursos alojados en cualquier servicio dado (como repositorios en un Docker Registry).
- Un Docker Registry capaz de confiar en el servidor de autorización para firmar los tokens que los clientes pueden utilizar para la autorización, y con la capacidad de verificar estos tokens para un solo uso o para su uso durante un período de tiempo suficientemente corto.

## Descripciones de los endpoints del servidor de autorización

El servidor descrito está destinado a servir como un gestor de control de acceso independiente para recursos alojados por otros servicios que desean autenticar y gestionar autorizaciones utilizando un gestor de control de acceso independiente.

Un servicio como este es utilizado por el Docker Registry oficial para autenticar a los clientes y verificar su autorización en los repositorios de imágenes de Docker.

A partir de Docker 1.6, el cliente de registry dentro de Docker Engine se ha actualizado para manejar dicho flujo de trabajo de autorización.

## Cómo autenticarse

Los clientes de Registry V1 contactan primero con el índice para iniciar un push o pull. Bajo el flujo de trabajo de Registry V2, los clientes deben contactar primero con el registry. Si el servidor de registry requiere autenticación, devolverá una respuesta `401 Unauthorized` con una cabecera `WWW-Authenticate` que detalla cómo autenticarse en este registry.

Por ejemplo, supongamos que yo (usuario `jlhawn`) estoy intentando enviar (push) una imagen al repositorio `samalba/my-app`. Para que el registry autorice esto, necesitaré acceso de `push` al repositorio `samalba/my-app`. El registry devolverá primero esta respuesta:

```text
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push"
Date: Thu, 10 Sep 2015 19:32:31 GMT
Content-Length: 235
Strict-Transport-Security: max-age=31536000

{"errors":[{"code":"UNAUTHORIZED","message":"access to the requested resource is not authorized","detail":[{"Type":"repository","Name":"samalba/my-app","Action":"pull"},{"Type":"repository","Name":"samalba/my-app","Action":"push"}]}]}
```

Ten en cuenta la cabecera de respuesta HTTP que indica el desafío de autenticación:

```text
Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push"
```

Este formato está documentado en la [Sección 3 del RFC 6750: El marco de autorización OAuth 2.0: Uso del token Bearer](https://tools.ietf.org/html/rfc6750#section-3).

Este desafío indica que el registry requiere un token emitido por el servidor de tokens especificado y que la solicitud que el cliente está intentando deberá incluir suficientes entradas de acceso en su conjunto de notificaciones (claim set). Para responder a este desafío, el cliente deberá realizar una solicitud `GET` a la URL `https://auth.docker.io/token` utilizando los valores de `service` y `scope` de la cabecera `WWW-Authenticate`.

## Solicitar un token

Define la obtención de un token bearer y de actualización (refresh token) utilizando el endpoint de token.

### Parámetros de consulta (Query parameters)

#### `service`

El nombre del servicio que aloja el recurso.

#### `offline_token`

Indica si se debe devolver un token de actualización junto con el token bearer. Un token de actualización es capaz de obtener tokens bearer adicionales para el mismo sujeto con diferentes alcances. El token de actualización no tiene fecha de caducidad y debe considerarse completamente opaco para el cliente.

#### `client_id`

Cadena que identifica al cliente. Este `client_id` no necesita estar registrado en el servidor de autorización, pero debe establecerse en un valor significativo para permitir la auditoría de claves creadas por clientes no registrados. La sintaxis aceptada se define en el [Apéndice A.1 del RFC6749](https://tools.ietf.org/html/rfc6749#appendix-A.1).

#### `scope`

El recurso en cuestión, formateado como una de las entradas delimitadas por espacios de los parámetros `scope` de la cabecera `WWW-Authenticate` mostrada anteriormente. Este parámetro de consulta debe especificarse varias veces si hay más de una entrada de `scope` en la cabecera `WWW-Authenticate`. El ejemplo anterior se especificaría como: `scope=repository:samalba/my-app:push`. El campo scope puede estar vacío para solicitar un token de actualización sin proporcionar ningún permiso de recurso al token bearer devuelto.

### Campos de respuesta del token

#### `token`

Un token `Bearer` opaco que los clientes deben suministrar en las solicitudes subsiguientes en la cabecera `Authorization`.

#### `access_token`

Por compatibilidad con OAuth 2.0, también se acepta el `token` bajo el nombre `access_token`. Debe especificarse al menos uno de estos campos, pero también pueden aparecer ambos (para compatibilidad con clientes más antiguos). Cuando se especifican ambos, deben ser equivalentes; si difieren, la elección del cliente es indefinida.

#### `expires_in`

(Opcional) La duración en segundos desde que se emitió el token durante la cual seguirá siendo válido. Cuando se omite, el valor predeterminado es 60 segundos. Para compatibilidad con clientes más antiguos, nunca se debe devolver un token con menos de 60 segundos de vida.

#### `issued_at`

(Opcional) La hora estándar UTC serializada en [RFC3339](https://www.ietf.org/rfc/rfc3339.txt) en la que se emitió un token dado. Si se omite `issued_at`, la expiración se cuenta desde que se completó el intercambio del token.

#### `refresh_token`

(Opcional) Token que se puede utilizar para obtener tokens de acceso adicionales para el mismo sujeto con diferentes alcances. Este token debe mantenerse seguro por el cliente y solo debe enviarse al servidor de autorización que emite los tokens bearer. Este campo solo se establecerá cuando se proporcione `offline_token=true` en la solicitud.

### Ejemplo

Para este ejemplo, el cliente realiza una solicitud HTTP GET a la siguiente URL:

```text
https://auth.docker.io/token?service=registry.docker.io&scope=repository:samalba/my-app:pull,push
```

El servidor de tokens debe intentar primero autenticar al cliente utilizando cualquier credencial de autenticación proporcionada con la solicitud. Desde Docker 1.11, Docker Engine admite tanto la autenticación básica (Basic Authentication) como OAuth2 para obtener tokens. En Docker 1.10 y anteriores, el cliente de registry en Docker Engine solo admite la autenticación básica. Si falla un intento de autenticación en el servidor de tokens, este debe devolver una respuesta `401 Unauthorized` indicando que las credenciales proporcionadas no son válidas.

El hecho de que el servidor de tokens requiera autenticación depende de la política de ese proveedor de control de acceso. Algunas solicitudes pueden requerir autenticación para determinar el acceso (como hacer push o pull en un repositorio privado), mientras que otras no (como hacer pull desde un repositorio público).

Después de autenticar al cliente (que puede ser simplemente un cliente anónimo si no se intentó la autenticación), el servidor de tokens debe consultar a continuación su lista de control de acceso para determinar si el cliente tiene el alcance solicitado. En esta solicitud de ejemplo, si me he autenticado como el usuario `jlhawn`, el servidor de tokens determinará qué acceso tengo al repositorio `samalba/my-app` alojado por la entidad `registry.docker.io`.

Una vez que el servidor de tokens ha determinado qué acceso tiene el cliente a los recursos solicitados en el parámetro `scope`, tomará la intersección del conjunto de acciones solicitadas en cada recurso y el conjunto de acciones que de hecho se le han concedido al cliente. Si el cliente solo tiene un subconjunto del acceso solicitado, **no debe considerarse un error**, ya que no es responsabilidad del servidor de tokens indicar errores de autorización como parte de este flujo de trabajo.

Continuando con la solicitud de ejemplo, el servidor de tokens encontrará que el conjunto de accesos concedidos del cliente al repositorio es `[pull, push]`, lo que al intersectarse con el acceso solicitado `[pull, push]` produce un conjunto igual. Si se descubriera que el conjunto de accesos concedidos fuera solo `[pull]`, entonces el conjunto intersectado sería únicamente `[pull]`. Si el cliente no tiene acceso al repositorio, el conjunto intersectado estaría vacío, `[]`.

Es este conjunto intersectado de accesos el que se coloca en el token devuelto.

A continuación, el servidor construye un token específico de la implementación con este conjunto intersectado de accesos, y lo devuelve al cliente de Docker para que lo use para autenticarse en el servicio de audiencia (dentro del período de tiempo indicado):

```text
HTTP/1.1 200 OK
Content-Type: application/json

{"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IlBZWU86VEVXVTpWN0pIOjI2SlY6QVFUWjpMSkMzOlNYVko6WEdIQTozNEYyOjJMQVE6WlJNSzpaN1E2In0.eyJpc3MiOiJhdXRoLmRvY2tlci5jb20iLCJzdWIiOiJqbGhhd24iLCJhdWQiOiJyZWdpc3RyeS5kb2NrZXIuY29tIiwiZXhwIjoxNDE1Mzg3MzE1LCJuYmYiOjE0MTUzODcwMTUsImlhdCI6MTQxNTM4NzAxNSwianRpIjoidFlKQ08xYzZjbnl5N2tBbjBjN3JLUGdiVjFIMWJGd3MiLCJhY2Nlc3MiOlt7InR5cGUiOiJyZXBvc2l0b3J5IiwibmFtZSI6InNhbWFsYmEvbXktYXBwIiwiYWN0aW9ucyI6WyJwdXNoIl19XX0.QhflHPfbd6eVF4lM9bwYpFZIV0PfikbyXuLx959ykRTBpe3CYnzs6YBK8FToVb5R47920PVLrh8zuLzdCr9t3w", "expires_in": 3600,"issued_at": "2009-11-10T23:00:00Z"}
```

## Usar el token Bearer

Una vez que el cliente tiene un token, volverá a intentar la solicitud al registry con el token colocado en la cabecera HTTP `Authorization` de esta manera:

```text
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IkJWM0Q6MkFWWjpVQjVaOktJQVA6SU5QTDo1RU42Ok40SjQ6Nk1XTzpEUktFOkJWUUs6M0ZKTDpQT1RMIn0.eyJpc3MiOiJhdXRoLmRvY2tlci5jb20iLCJzdWIiOiJCQ0NZOk9VNlo6UUVKNTpXTjJDOjJBVkM6WTdZRDpBM0xZOjQ1VVc6NE9HRDpLQUxMOkNOSjU6NUlVTCIsImF1ZCI6InJlZ2lzdHJ5LmRvY2tlci5jb20iLCJleHAiOjE0MTUzODczMTUsIm5iZiI6MTQxNTM4NzAxNSwiaWF0IjoxNDE1Mzg3MDE1LCJqdGkiOiJ0WUpDTzFjNmNueXk3a0FuMGM3cktQZ2JWMUgxYkZ3cyIsInNjb3BlIjoiamxoYXduOnJlcG9zaXRvcnk6c2FtYWxiYS9teS1hcHA6cHVzaCxwdWxsIGpsaGF3bjpuYW1lc3BhY2U6c2FtYWxiYTpwdWxsIn0.Y3zZSwaZPqy4y9oRBVRImZyv3m_S9XDHF1tWwN7mL52C_IiA73SJkWVNsvNqpJIn5h7A2F8biv_S2ppQ1lgkbw
```

Esto también se describe en la [Sección 2.1 del RFC 6750: El marco de autorización OAuth 2.0: Uso del token Bearer](https://tools.ietf.org/html/rfc6750#section-2.1).
