diff --git a/docs/spec/auth/token.md b/docs/spec/auth/token.md
index 4b9a52a1d..8563d7e56 100644
--- a/docs/spec/auth/token.md
+++ b/docs/spec/auth/token.md
@@ -46,7 +46,7 @@ the above process by using cryptographically signed tokens and no longer
require the client to authenticate each request with a username and password
stored locally in plain text.
-The new registry workflow is more like this:
+The v2 registry token workflow is more like this:
![v2 registry auth](https://docs.google.com/drawings/d/1EHZU9uBLmcH0kytDClBv6jv6WR4xZjE8RKEUw1mARJA/pub?w=480&h=360)
@@ -55,19 +55,20 @@ The new registry workflow is more like this:
HTTP response with information on how to authenticate.
3. The registry client makes a request to the authorization service for a
signed JSON Web Token.
-4. The authorization service returns a token.
+4. The authorization service returns an opaque token representing the client's
+ authorized access.
5. The client retries the original request with the token embedded in the
request header.
-6. The Registry authorizes the client and begins the push/pull session as
- usual.
+6. The Registry authorizes the client by validating the token and the claim set
+ embedded within it and begins the push/pull session as usual.
## Requirements
-- Registry Clients capable of generating key pairs which can be used to
- authenticate to an authorization server.
-- An authorization server capable of managing user accounts, their public keys,
- and access controls to their resources hosted by any given service (such as
- repositories in a Docker Registry).
+- Registry clients which can understand and respond to token auth challenges
+ returned by the resource server.
+- An authorization server capable of managing access controls to their
+ resources hosted by any given service (such as repositories in a Docker
+ Registry).
- A Docker Registry capable of trusting the authorization server to sign tokens
which clients can use for authorization and the ability to verify these
tokens for single use or for use during a sufficiently short period of time.
@@ -76,39 +77,55 @@ The new registry workflow is more like this:
This document borrows heavily from the [JSON Web Token Draft Spec](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32)
-The described server is meant to serve as a user account and key manager and a
-centralized access control list for resources hosted by other services which
-wish to authenticate and manage authorizations using this services accounts and
-their public keys.
+The described server is meant to serve as a standalone access control manager
+for resources hosted by other services which wish to authenticate and manage
+authorizations using a separate access control manager.
-Such a service could be used by the official docker registry to authenticate
-clients and verify their authorization to docker image repositories.
+Such a service could be used by the official Docker Registry to authenticate
+clients and verify their authorization to Docker image repositories.
-Docker will need to be updated to interact with an authorization server to get
-an authorization token.
+As of Docker 1.6, the registry client within the Docker Engine has been updated
+to handle such an authorization workflow.
## How to authenticate
-Today, registry clients first contact the index to initiate a push or pull.
-For v2, clients should contact the registry first. If the registry server
-requires authentication it will return a `401 Unauthorized` response with a
-`WWW-Authenticate` header detailing how to authenticate to this registry.
+Registry V1 clients first contact the index to initiate a push or pull. Under
+the Registry V2 workflow, clients should contact the registry first. If the
+registry server requires authentication it will return a `401 Unauthorized`
+response with a `WWW-Authenticate` header detailing how to authenticate to this
+registry.
For example, say I (username `jlhawn`) am attempting to push an image to the
-repository `samalba/my-app`. For the registry to authorize this, I either need
-`push` access to the `samalba/my-app` repository or `push` access to the whole
-`samalba` namespace in general. The registry will first return this response:
+repository `samalba/my-app`. For the registry to authorize this, I will need
+`push` access to the `samalba/my-app` repository. The registry will first
+return this response:
```
HTTP/1.1 401 Unauthorized
-WWW-Authenticate: Bearer realm="https://auth.docker.com/v2/token/",service="registry.docker.com",scope="repository:samalba/my-app:push"
+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"}]}]}
+```
+
+Note the HTTP Response Header indicating the auth challenge:
+
+```
+Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push"
```
This 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)
-The client will then know to make a `GET` request to the URL
-`https://auth.docker.com/v2/token/` using the `service` and `scope` values from
-the `WWW-Authenticate` header.
+This challenge indicates that the registry requires a token issued by the
+specified token server and that the request the client is attempting will
+need to include sufficient access entries in its claim set. To respond to this
+challenge, the client will need to make a `GET` request to the URL
+`https://auth.docker.io/token` using the `service` and `scope` values from the
+`WWW-Authenticate` header.
## Requesting a Token
@@ -132,45 +149,51 @@ the `WWW-Authenticate` header.
header. The above example would be specified as:
scope=repository:samalba/my-app:push
.
-
account
- sub
(Subject)
aud
(Audience)
exp
(Expiration)
@@ -305,6 +330,7 @@ Token has 3 main parts:
"type": "repository",
"name": "samalba/my-app",
"actions": [
+ "pull",
"push"
]
}
@@ -416,8 +442,16 @@ claim set within. The registry will:
level of access for the operation the client is attempting to perform.
- Verify that the signature of the token is valid.
-At no point in this process should the registry need to call back to
-the authorization server. If anything, it would only need to update a list of
-trusted public keys for verifying token signatures or use a separate API
-(still to be spec'd) to add/update resource records on the authorization
-server.
+If any of these requirements are not met, the registry will return a
+`403 Forbidden` response to indicate that the token is invalid.
+
+**Note**: it is only at this point in the workflow that an authorization error
+may occur. The token server should *not* return errors when the user does not
+have the requested authorization. Instead, the returned token should indicate
+whatever of the requested scope the client does have (the intersection of
+requested and granted access). If the token does not supply proper
+authorization then the registry will return the appropriate error.
+
+At no point in this process should the registry need to call back to the
+authorization server. The registry only needs to be supplied with the trusted
+public keys to verify the token signatures.