diff --git a/docs/spec/auth/index.md b/docs/spec/auth/index.md
index 2d1740e8..b123af1a 100644
--- a/docs/spec/auth/index.md
+++ b/docs/spec/auth/index.md
@@ -8,5 +8,7 @@ keywords = ["registry, on-prem, images, tags, repository, distribution, authenti
# Docker Registry v2 authentication
-See the [Token Authentication Specification](token.md) and
-[Token Authentication Implementation](jwt.md) for more information.
+See the [Token Authentication Specification](token.md),
+[Token Authentication Implementation](jwt.md),
+[Token Scope Documentation](scope.md),
+[OAuth2 Token Authentication](oauth.md) for more information.
diff --git a/docs/spec/auth/oauth.md b/docs/spec/auth/oauth.md
new file mode 100644
index 00000000..b0f9a13f
--- /dev/null
+++ b/docs/spec/auth/oauth.md
@@ -0,0 +1,190 @@
+
+
+# Docker Registry v2 authentication using OAuth2
+
+This document describes support for the OAuth2 protocol within the authorization
+server. [RFC6749](https://tools.ietf.org/html/rfc6749) should be used as a
+reference for the protocol and HTTP endpoints described here.
+
+## Refresh token format
+
+The format of the refresh token is completely opaque to the client and should be
+determined by the authorization server. The authorization should ensure the
+token is sufficiently long and is responsible for storing any information about
+long-lived tokens which may be needed for revoking. Any information stored
+inside the token will not be extracted and presented by clients.
+
+## Getting a token
+
+POST /token
+
+#### Headers
+Content-Type: application/x-www-form-urlencoded
+
+#### Post parameters
+
+
+ -
+
grant_type
+
+ -
+ (REQUIRED) Type of grant used to get token. When getting a refresh token
+ using credentials this type should be set to "password" and have the
+ accompanying username and password paramters. Type "authorization_code"
+ is reserved for future use for authenticating to an authorization server
+ without having to send credentials directly from the client. When
+ requesting an access token with a refresh token this should be set to
+ "refresh_token".
+
+ -
+
service
+
+ -
+ (REQUIRED) The name of the service which hosts the resource to get
+ access for. Refresh tokens will only be good for getting tokens for
+ this service.
+
+ -
+
client_id
+
+ -
+ (REQUIRED) String identifying the client. This client_id does not need
+ to be registered with the authorization server but should be set to a
+ meaningful value in order to allow auditing keys created by unregistered
+ clients. Accepted syntax is defined in
+ [RFC6749 Appendix A.1](https://tools.ietf.org/html/rfc6749#appendix-A.1)
+
+ -
+
access_type
+
+ -
+ (OPTIONAL) Access which is being requested. If "offline" is provided
+ then a refresh token will be returned. The default is "online" only
+ returning short lived access token. If the grant type is "refresh_token"
+ this will only return the same refresh token and not a new one.
+
+ -
+
scope
+
+ -
+ (OPTIONAL) The resource in question, formatted as one of the space-delimited
+ entries from the
scope
parameters from the WWW-Authenticate
header
+ shown above. This query parameter should only be specified once but may
+ contain multiple scopes using the scope list format defined in the scope
+ grammar. If multiple scope
is provided from
+ WWW-Authenticate
header the scopes should first be
+ converted to a scope list before requesting the token. The above example
+ would be specified as: scope=repository:samalba/my-app:push
.
+ When requesting a refresh token the scopes may be empty since the
+ refresh token will not be limited by this scope, only the provided short
+ lived access token will have the scope limitation.
+
+ -
+
refresh_token
+
+ -
+ (OPTIONAL) The refresh token to use for authentication when grant type "refresh_token" is used.
+
+ -
+
username
+
+ -
+ (OPTIONAL) The username to use for authentication when grant type "password" is used.
+
+ -
+
password
+
+ -
+ (OPTIONAL) The password to use for authentication when grant type "password" is used.
+
+
+
+#### Response fields
+
+
+ -
+
access_token
+
+ -
+ (REQUIRED) An opaque
Bearer
token that clients should
+ supply to subsequent requests in the Authorization
header.
+ This token should not be attempted to be parsed or understood by the
+ client but treated as opaque string.
+
+ -
+
scope
+
+ -
+ (REQUIRED) The scope granted inside the access token. This may be the
+ same scope as requested or a subset. This requirement is stronger than
+ specified in [RFC6749 Section 4.2.2](https://tools.ietf.org/html/rfc6749#section-4.2.2)
+ by strictly requiring the scope in the return value.
+
+ -
+
expires_in
+
+ -
+ (REQUIRED) The duration in seconds since the token was issued that it
+ will remain valid. When omitted, this defaults to 60 seconds. For
+ compatibility with older clients, a token should never be returned with
+ less than 60 seconds to live.
+
+ -
+
issued_at
+
+ -
+ (Optional) The RFC3339-serialized UTC
+ standard time at which a given token was issued. If
issued_at
is omitted, the
+ expiration is from when the token exchange completed.
+
+ -
+
refresh_token
+
+ -
+ (Optional) Token which can be used to get additional access tokens for
+ the same subject with different scopes. This token should be kept secure
+ by the client and only sent to the authorization server which issues
+ bearer tokens. This field will only be set when `access_type=offline` is
+ provided in the request.
+
+
+
+
+#### Example getting refresh token
+
+```
+POST /token HTTP/1.1
+Host: auth.docker.io
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=password&username=johndoe&password=A3ddj3w&service=hub.docker.io&client_id=dockerengine&access_type=offline
+
+HTTP/1.1 200 OK
+Content-Type: application/json
+
+{"refresh_token":"kas9Da81Dfa8","access_token":"eyJhbGciOiJFUzI1NiIsInR5","expires_in":"900","scope":""}
+````
+
+#### Example refreshing an Access Token
+
+````
+POST /token HTTP/1.1
+Host: auth.docker.io
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=refresh_token&refresh_token=kas9Da81Dfa8&service=registry-1.docker.io&client_id=dockerengine&scope=repository:samalba/my-app:pull,push
+
+HTTP/1.1 200 OK
+Content-Type: application/json
+
+{"refresh_token":"kas9Da81Dfa8","access_token":"eyJhbGciOiJFUzI1NiIsInR5":"expires_in":"900","scope":"repository:samalba/my-app:pull,repository:samalba/my-app:push"}
+````
+
diff --git a/docs/spec/auth/scope.md b/docs/spec/auth/scope.md
new file mode 100644
index 00000000..76e6f8cf
--- /dev/null
+++ b/docs/spec/auth/scope.md
@@ -0,0 +1,134 @@
+
+
+# Docker Registry Token Scope and Access
+
+Tokens used by the registry are always restricted what resources they may
+be used to access, where those resources may be accessed, and what actions
+may be done on those resources. Tokens always have the context of a user which
+the token was originally created for. This document describes how these
+restrictions are represented and enforced by the authorization server and
+resource providers.
+
+## Scope Components
+
+### Subject (Authenticated User)
+
+The subject represents the user for which a token is valid. Any actions
+performed using an access token should be considered on behalf of the subject.
+This is included in the `sub` field of access token JWT. A refresh token should
+be limited to a single subject and only be able to give out access tokens for
+that subject.
+
+### Audience (Resource Provider)
+
+The audience represents a resource provider which is intended to be able to
+perform the actions specified in the access token. Any resource provider which
+does not match the audience should not use that access token. The audience is
+included in the `aud` field of the access token JWT. A refresh token should be
+limited to a single audience and only be able to give out access tokens for that
+audience.
+
+### Resource Type
+
+The resource type represents the type of resource which the resource name is
+intended to represent. This type may be specific to a resource provider but must
+be understood by the authorization server in order to validate the subject
+is authorized for a specific resource.
+
+#### Example Resource Types
+
+ - `repository` - represents a single repository within a registry. A
+repository may represent many manifest or content blobs, but the resource type
+is considered the collections of those items. Actions which may be performed on
+a `repository` are `pull` for accessing the collection and `push` for adding to
+it.
+
+### Resource Name
+
+The resource name represent the name which identifies a resource for a resource
+provider. A resource is identified by this name and the provided resource type.
+An example of a resource name would be the name component of an image tag, such
+as "samalba/myapp".
+
+### Resource Actions
+
+The resource actions define the actions which the access token allows to be
+performed on the identified resource. These actions are type specific but will
+normally have actions identifying read and write access on the resource. Example
+for the `repository` type are `pull` for read access and `push` for write
+access.
+
+## Authorization Server Use
+
+Each access token request may include a scope and an audience. The subject is
+always derived from the passed in credentials or refresh token. When using
+a refresh token the passed in audience must match the audience defined for
+the refresh token. The audience (resource provider) is provided using the
+`service` field. Multiple resource scopes may be provided using multiple `scope`
+fields on the `GET` request. The `POST` request only takes in a single
+`scope` field but may use a space to separate a list of multiple resource
+scopes.
+
+### Resource Scope Grammar
+
+```
+scope := resourcescope [ ' ' resourcescope ]*
+resourcescope := resourcetype ":" resourcename ":" action [ ',' action ]*
+resourcetype := /[a-z]*/
+resourcename := component [ '/' component ]*
+action := /[a-z]*/
+component := alpha-numeric [ separator alpha-numeric ]*
+alpha-numeric := /[a-z0-9]+/
+separator := /[_.]|__|[-]*/
+```
+Full reference grammar is defined
+(here)[https://godoc.org/github.com/docker/distribution/reference]. Currently
+the scope name grammar is a subset of the reference grammar without support
+for hostnames.
+
+## Resource Provider Use
+
+Once a resource provider has verified the authenticity of the scope through
+JWT access token verification, the resource provider must ensure that scope
+satisfies the request. The resource provider should match the given audience
+according to name or URI the resource provider uses to identify itself. Any
+denial based on subject is not defined here and is up to resource provider, the
+subject is mainly provided for audit logs and any other user-specific rules
+which may need to be provided but are not defined by the authorization server.
+
+The resource provider must ensure that ANY resource being accessed as the
+result of a request has the appropriate access scope. Both the resource type
+and resource name must match the accessed resource and an appropriate action
+scope must be included.
+
+When appropriate authorization is not provided either due to lack of scope
+or missing token, the resource provider to return a `WWW-AUTHENTICATE` HTTP
+header with the `realm` as the authorization server, the `service` as the
+expected audience identifying string, and a `scope` field for each required
+resource scope to complete the request.
+
+## JWT Access Tokens
+
+Each JWT access token may only have a single subject and audience but multiple
+resource scopes. The subject and audience are put into standard JWT fields
+`sub` and `aud`. The resource scope is put into the `access` field. The
+structure of the access field can be seen in the
+[jwt documentation](jwt.md).
+
+## Refresh Tokens
+
+A refresh token must be defined for a single subject and audience. Further
+restricting scope to specific type, name, and actions combinations should be
+done by fetching an access token using the refresh token. Since the refresh
+token is not scoped to specific resources for an audience, extra care should
+be taken to only use the refresh token to negotiate new access tokens directly
+with the authorization server, and never with a resource provider.
+
diff --git a/docs/spec/auth/token.md b/docs/spec/auth/token.md
index 61e893c0..9f3167be 100644
--- a/docs/spec/auth/token.md
+++ b/docs/spec/auth/token.md
@@ -91,6 +91,8 @@ challenge, the client will need to make a `GET` request to the URL
## Requesting a Token
+Defines getting a bearer and refresh token using the token endpoint.
+
#### Query Parameters
@@ -100,6 +102,25 @@ challenge, the client will need to make a `GET` request to the URL
-
The name of the service which hosts the resource.
+ -
+
offline_token
+
+ -
+ Whether to return a refresh token along with the bearer token. A refresh
+ token is capable of getting additional bearer tokens for the same
+ subject with different scopes. The refresh token does not have an
+ expiration and should be considered completely opaque to the client.
+
+ -
+
client_id
+
+ -
+ String identifying the client. This client_id does not need
+ to be registered with the authorization server but should be set to a
+ meaningful value in order to allow auditing keys created by unregistered
+ clients. Accepted syntax is defined in
+ [RFC6749 Appendix A.1](https://tools.ietf.org/html/rfc6749#appendix-A.1).
+
-
scope
@@ -109,7 +130,9 @@ challenge, the client will need to make a `GET` request to the URL
shown above. This query parameter should be specified multiple times if
there is more than one scope
entry from the WWW-Authenticate
header. The above example would be specified as:
- scope=repository:samalba/my-app:push
.
+ scope=repository:samalba/my-app:push
. The scope field may
+ be empty to request a refresh token without providing any resource
+ permissions to the returned bearer token.
@@ -150,6 +173,16 @@ challenge, the client will need to make a `GET` request to the URL
standard time at which a given token was issued. If issued_at
is omitted, the
expiration is from when the token exchange completed.
+
+ refresh_token
+
+
+ (Optional) Token which can be used to get additional access tokens for
+ the same subject with different scopes. This token should be kept secure
+ by the client and only sent to the authorization server which issues
+ bearer tokens. This field will only be set when `offline_token=true` is
+ provided in the request.
+
#### Example
@@ -161,11 +194,12 @@ https://auth.docker.io/token?service=registry.docker.io&scope=repository:samalba
```
The token server should first attempt to authenticate the client using any
-authentication credentials provided with the request. As of Docker 1.8, the
-registry client in the Docker Engine only supports Basic Authentication to
-these token servers. If an attempt to authenticate to the token server fails,
-the token server should return a `401 Unauthorized` response indicating that
-the provided credentials are invalid.
+authentication credentials provided with the request. From Docker 1.11 the
+Docker engine supports both Basic Authentication and [OAuth2](oauth.md) for
+getting tokens. Docker 1.10 and before, the registry client in the Docker Engine
+only supports Basic Authentication. If an attempt to authenticate to the token
+server fails, the token server should return a `401 Unauthorized` response
+indicating that the provided credentials are invalid.
Whether the token server requires authentication is up to the policy of that
access control provider. Some requests may require authentication to determine