...

Text file src/github.com/docker/distribution/docs/spec/auth/token.md

Documentation: github.com/docker/distribution/docs/spec/auth

     1---
     2title: "Token Authentication Specification"
     3description: "Specifies the Docker Registry v2 authentication"
     4keywords: registry, on-prem, images, tags, repository, distribution, Bearer authentication, advanced
     5---
     6
     7# Docker Registry v2 authentication via central service
     8
     9This document outlines the v2 Docker registry authentication scheme:
    10
    11![v2 registry auth](../images/v2-registry-auth.png)
    12
    131. Attempt to begin a push/pull operation with the registry.
    142. If the registry requires authorization it will return a `401 Unauthorized`
    15   HTTP response with information on how to authenticate.
    163. The registry client makes a request to the authorization service for a
    17   Bearer token.
    184. The authorization service returns an opaque Bearer token representing the
    19   client's authorized access.
    205. The client retries the original request with the Bearer token embedded in
    21   the request's Authorization header.
    226. The Registry authorizes the client by validating the Bearer token and the
    23   claim set embedded within it and begins the push/pull session as usual.
    24
    25## Requirements
    26
    27- Registry clients which can understand and respond to token auth challenges
    28  returned by the resource server.
    29- An authorization server capable of managing access controls to their
    30  resources hosted by any given service (such as repositories in a Docker
    31  Registry).
    32- A Docker Registry capable of trusting the authorization server to sign tokens
    33  which clients can use for authorization and the ability to verify these
    34  tokens for single use or for use during a sufficiently short period of time.
    35
    36## Authorization Server Endpoint Descriptions
    37
    38The described server is meant to serve as a standalone access control manager
    39for resources hosted by other services which wish to authenticate and manage
    40authorizations using a separate access control manager.
    41
    42A service like this is used by the official Docker Registry to authenticate
    43clients and verify their authorization to Docker image repositories.
    44
    45As of Docker 1.6, the registry client within the Docker Engine has been updated
    46to handle such an authorization workflow.
    47
    48## How to authenticate
    49
    50Registry V1 clients first contact the index to initiate a push or pull. Under
    51the Registry V2 workflow, clients should contact the registry first. If the
    52registry server requires authentication it will return a `401 Unauthorized`
    53response with a `WWW-Authenticate` header detailing how to authenticate to this
    54registry.
    55
    56For example, say I (username `jlhawn`) am attempting to push an image to the
    57repository `samalba/my-app`. For the registry to authorize this, I will need
    58`push` access to the `samalba/my-app` repository. The registry will first
    59return this response:
    60
    61```
    62HTTP/1.1 401 Unauthorized
    63Content-Type: application/json; charset=utf-8
    64Docker-Distribution-Api-Version: registry/2.0
    65Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push"
    66Date: Thu, 10 Sep 2015 19:32:31 GMT
    67Content-Length: 235
    68Strict-Transport-Security: max-age=31536000
    69
    70{"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"}]}]}
    71```
    72
    73Note the HTTP Response Header indicating the auth challenge:
    74
    75```
    76Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push"
    77```
    78
    79This format is documented in [Section 3 of RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage](https://tools.ietf.org/html/rfc6750#section-3)
    80
    81This challenge indicates that the registry requires a token issued by the
    82specified token server and that the request the client is attempting will
    83need to include sufficient access entries in its claim set. To respond to this
    84challenge, the client will need to make a `GET` request to the URL
    85`https://auth.docker.io/token` using the `service` and `scope` values from the
    86`WWW-Authenticate` header.
    87
    88## Requesting a Token
    89
    90Defines getting a bearer and refresh token using the token endpoint.
    91
    92#### Query Parameters
    93
    94<dl>
    95    <dt>
    96        <code>service</code>
    97    </dt>
    98    <dd>
    99        The name of the service which hosts the resource.
   100    </dd>
   101    <dt>
   102        <code>offline_token</code>
   103    </dt>
   104    <dd>
   105        Whether to return a refresh token along with the bearer token. A refresh
   106        token is capable of getting additional bearer tokens for the same
   107        subject with different scopes. The refresh token does not have an
   108        expiration and should be considered completely opaque to the client.
   109    </dd>
   110    <dt>
   111        <code>client_id</code>
   112    </dt>
   113    <dd>
   114        String identifying the client. This client_id does not need
   115        to be registered with the authorization server but should be set to a
   116        meaningful value in order to allow auditing keys created by unregistered
   117        clients. Accepted syntax is defined in
   118        [RFC6749 Appendix A.1](https://tools.ietf.org/html/rfc6749#appendix-A.1).
   119    </dd>
   120    <dt>
   121        <code>scope</code>
   122    </dt>
   123    <dd>
   124        The resource in question, formatted as one of the space-delimited
   125        entries from the <code>scope</code> parameters from the <code>WWW-Authenticate</code> header
   126        shown above. This query parameter should be specified multiple times if
   127        there is more than one <code>scope</code> entry from the <code>WWW-Authenticate</code>
   128        header. The above example would be specified as:
   129        <code>scope=repository:samalba/my-app:push</code>. The scope field may
   130        be empty to request a refresh token without providing any resource
   131        permissions to the returned bearer token.
   132    </dd>
   133</dl>
   134
   135
   136#### Token Response Fields
   137
   138<dl>
   139    <dt>
   140        <code>token</code>
   141    </dt>
   142    <dd>
   143        An opaque <code>Bearer</code> token that clients should supply to subsequent
   144        requests in the <code>Authorization</code> header.
   145    </dd>
   146    <dt>
   147        <code>access_token</code>
   148    </dt>
   149    <dd>
   150        For compatibility with OAuth 2.0, we will also accept <code>token</code> under the name
   151        <code>access_token</code>.  At least one of these fields <b>must</b> be specified, but
   152        both may also appear (for compatibility with older clients).  When both are specified,
   153        they should be equivalent; if they differ the client's choice is undefined.
   154    </dd>
   155    <dt>
   156        <code>expires_in</code>
   157    </dt>
   158    <dd>
   159        (Optional) The duration in seconds since the token was issued that it
   160        will remain valid.  When omitted, this defaults to 60 seconds.  For
   161        compatibility with older clients, a token should never be returned with
   162        less than 60 seconds to live.
   163    </dd>
   164    <dt>
   165        <code>issued_at</code>
   166    </dt>
   167    <dd>
   168        (Optional) The <a href="https://www.ietf.org/rfc/rfc3339.txt">RFC3339</a>-serialized UTC
   169        standard time at which a given token was issued. If <code>issued_at</code> is omitted, the
   170        expiration is from when the token exchange completed.
   171    </dd>
   172    <dt>
   173        <code>refresh_token</code>
   174    </dt>
   175    <dd>
   176        (Optional) Token which can be used to get additional access tokens for
   177        the same subject with different scopes. This token should be kept secure
   178        by the client and only sent to the authorization server which issues
   179        bearer tokens. This field will only be set when `offline_token=true` is
   180        provided in the request.
   181    </dd>
   182</dl>
   183
   184#### Example
   185
   186For this example, the client makes an HTTP GET request to the following URL:
   187
   188```
   189https://auth.docker.io/token?service=registry.docker.io&scope=repository:samalba/my-app:pull,push
   190```
   191
   192The token server should first attempt to authenticate the client using any
   193authentication credentials provided with the request. From Docker 1.11 the
   194Docker engine supports both Basic Authentication and [OAuth2](oauth.md) for
   195getting tokens. Docker 1.10 and before, the registry client in the Docker Engine
   196only supports Basic Authentication. If an attempt to authenticate to the token
   197server fails, the token server should return a `401 Unauthorized` response
   198indicating that the provided credentials are invalid.
   199
   200Whether the token server requires authentication is up to the policy of that
   201access control provider. Some requests may require authentication to determine
   202access (such as pushing or pulling a private repository) while others may not
   203(such as pulling from a public repository).
   204
   205After authenticating the client (which may simply be an anonymous client if
   206no attempt was made to authenticate), the token server must next query its
   207access control list to determine whether the client has the requested scope. In
   208this example request, if I have authenticated as user `jlhawn`, the token
   209server will determine what access I have to the repository `samalba/my-app`
   210hosted by the entity `registry.docker.io`.
   211
   212Once the token server has determined what access the client has to the
   213resources requested in the `scope` parameter, it will take the intersection of
   214the set of requested actions on each resource and the set of actions that the
   215client has in fact been granted. If the client only has a subset of the
   216requested access **it must not be considered an error** as it is not the
   217responsibility of the token server to indicate authorization errors as part of
   218this workflow.
   219
   220Continuing with the example request, the token server will find that the
   221client's set of granted access to the repository is `[pull, push]` which when
   222intersected with the requested access `[pull, push]` yields an equal set. If
   223the granted access set was found only to be `[pull]` then the intersected set
   224would only be `[pull]`. If the client has no access to the repository then the
   225intersected set would be empty, `[]`.
   226
   227It is this intersected set of access which is placed in the returned token.
   228
   229The server then constructs an implementation-specific token with this
   230intersected set of access, and returns it to the Docker client to use to
   231authenticate to the audience service (within the indicated window of time):
   232
   233```
   234HTTP/1.1 200 OK
   235Content-Type: application/json
   236
   237{"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IlBZWU86VEVXVTpWN0pIOjI2SlY6QVFUWjpMSkMzOlNYVko6WEdIQTozNEYyOjJMQVE6WlJNSzpaN1E2In0.eyJpc3MiOiJhdXRoLmRvY2tlci5jb20iLCJzdWIiOiJqbGhhd24iLCJhdWQiOiJyZWdpc3RyeS5kb2NrZXIuY29tIiwiZXhwIjoxNDE1Mzg3MzE1LCJuYmYiOjE0MTUzODcwMTUsImlhdCI6MTQxNTM4NzAxNSwianRpIjoidFlKQ08xYzZjbnl5N2tBbjBjN3JLUGdiVjFIMWJGd3MiLCJhY2Nlc3MiOlt7InR5cGUiOiJyZXBvc2l0b3J5IiwibmFtZSI6InNhbWFsYmEvbXktYXBwIiwiYWN0aW9ucyI6WyJwdXNoIl19XX0.QhflHPfbd6eVF4lM9bwYpFZIV0PfikbyXuLx959ykRTBpe3CYnzs6YBK8FToVb5R47920PVLrh8zuLzdCr9t3w", "expires_in": 3600,"issued_at": "2009-11-10T23:00:00Z"}
   238```
   239
   240
   241## Using the Bearer token
   242
   243Once the client has a token, it will try the registry request again with the
   244token placed in the HTTP `Authorization` header like so:
   245
   246```
   247Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IkJWM0Q6MkFWWjpVQjVaOktJQVA6SU5QTDo1RU42Ok40SjQ6Nk1XTzpEUktFOkJWUUs6M0ZKTDpQT1RMIn0.eyJpc3MiOiJhdXRoLmRvY2tlci5jb20iLCJzdWIiOiJCQ0NZOk9VNlo6UUVKNTpXTjJDOjJBVkM6WTdZRDpBM0xZOjQ1VVc6NE9HRDpLQUxMOkNOSjU6NUlVTCIsImF1ZCI6InJlZ2lzdHJ5LmRvY2tlci5jb20iLCJleHAiOjE0MTUzODczMTUsIm5iZiI6MTQxNTM4NzAxNSwiaWF0IjoxNDE1Mzg3MDE1LCJqdGkiOiJ0WUpDTzFjNmNueXk3a0FuMGM3cktQZ2JWMUgxYkZ3cyIsInNjb3BlIjoiamxoYXduOnJlcG9zaXRvcnk6c2FtYWxiYS9teS1hcHA6cHVzaCxwdWxsIGpsaGF3bjpuYW1lc3BhY2U6c2FtYWxiYTpwdWxsIn0.Y3zZSwaZPqy4y9oRBVRImZyv3m_S9XDHF1tWwN7mL52C_IiA73SJkWVNsvNqpJIn5h7A2F8biv_S2ppQ1lgkbw
   248```
   249
   250This is also described in [Section 2.1 of RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage](https://tools.ietf.org/html/rfc6750#section-2.1)

View as plain text