Merge pull request #1418 from dmcgowan/oauth-spec
Add specification for using OAuth with the token servermaster
						commit
						a11f6b6cfd
					
				|  | @ -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. | ||||
|  |  | |||
|  | @ -0,0 +1,190 @@ | |||
| <!--[metadata]> | ||||
| +++ | ||||
| title = "Oauth2 Token Authentication" | ||||
| description = "Specifies the Docker Registry v2 authentication" | ||||
| keywords = ["registry, on-prem, images, tags, repository, distribution, oauth2, advanced"] | ||||
| [menu.main] | ||||
| parent="smn_registry_ref" | ||||
| +++ | ||||
| <![end-metadata]--> | ||||
| 
 | ||||
| # 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 | ||||
| 
 | ||||
| <dl> | ||||
|     <dt> | ||||
|         <code>grant_type</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (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". | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>service</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (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. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>client_id</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (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) | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>access_type</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (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. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>scope</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (OPTIONAL) The resource in question, formatted as one of the space-delimited | ||||
|         entries from the <code>scope</code> parameters from the <code>WWW-Authenticate</code> 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 <code>scope</code> is provided from | ||||
|         <code>WWW-Authenticate</code> header the scopes should first be | ||||
|         converted to a scope list before requesting the token. The above example | ||||
|         would be specified as: <code>scope=repository:samalba/my-app:push</code>. | ||||
|         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. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>refresh_token</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (OPTIONAL) The refresh token to use for authentication when grant type "refresh_token" is used. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>username</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (OPTIONAL) The username to use for authentication when grant type "password" is used. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>password</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (OPTIONAL) The password to use for authentication when grant type "password" is used. | ||||
|     </dd> | ||||
| </dl> | ||||
| 
 | ||||
| #### Response fields | ||||
| 
 | ||||
| <dl> | ||||
|     <dt> | ||||
|         <code>access_token</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (REQUIRED) An opaque <code>Bearer</code> token that clients should | ||||
|         supply to subsequent requests in the <code>Authorization</code> header. | ||||
|         This token should not be attempted to be parsed or understood by the | ||||
|         client but treated as opaque string. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>scope</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (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. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>expires_in</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (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. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>issued_at</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (Optional) The <a href="https://www.ietf.org/rfc/rfc3339.txt">RFC3339</a>-serialized UTC | ||||
|         standard time at which a given token was issued. If <code>issued_at</code> is omitted, the | ||||
|         expiration is from when the token exchange completed. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>refresh_token</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (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. | ||||
|     </dd> | ||||
| </dl> | ||||
| 
 | ||||
| 
 | ||||
| #### 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"} | ||||
| ```` | ||||
| 
 | ||||
|  | @ -0,0 +1,134 @@ | |||
| <!--[metadata]> | ||||
| +++ | ||||
| title = "Token Scope Documentation" | ||||
| description = "Describes the scope and access fields used for registry authorization tokens" | ||||
| keywords = ["registry, on-prem, images, tags, repository, distribution, advanced, access, scope"] | ||||
| [menu.main] | ||||
| parent="smn_registry_ref" | ||||
| +++ | ||||
| <![end-metadata]--> | ||||
| 
 | ||||
| # 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. | ||||
| 
 | ||||
|  | @ -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 | ||||
| 
 | ||||
| <dl> | ||||
|  | @ -100,6 +102,25 @@ challenge, the client will need to make a `GET` request to the URL | |||
|     <dd> | ||||
|         The name of the service which hosts the resource. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>offline_token</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         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. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>client_id</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         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). | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>scope</code> | ||||
|     </dt> | ||||
|  | @ -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 <code>scope</code> entry from the <code>WWW-Authenticate</code> | ||||
|         header. The above example would be specified as: | ||||
|         <code>scope=repository:samalba/my-app:push</code>. | ||||
|         <code>scope=repository:samalba/my-app:push</code>. The scope field may | ||||
|         be empty to request a refresh token without providing any resource | ||||
|         permissions to the returned bearer token. | ||||
|     </dd> | ||||
| </dl> | ||||
| 
 | ||||
|  | @ -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 <code>issued_at</code> is omitted, the | ||||
|         expiration is from when the token exchange completed. | ||||
|     </dd> | ||||
|     <dt> | ||||
|         <code>refresh_token</code> | ||||
|     </dt> | ||||
|     <dd> | ||||
|         (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. | ||||
|     </dd> | ||||
| </dl> | ||||
| 
 | ||||
| #### 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 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue