docker_auth icon indicating copy to clipboard operation
docker_auth copied to clipboard

Feature Request: Prolong token lifetime through Refresh tokens (request for comments)

Open kwk opened this issue 8 years ago • 2 comments

Hi,

I'm not sure if this is the plan behind PR #29 but I wanted to propose a mechanism to be able to prolong the lifetime of a token.

Use case

Normally, you're probably going to use the auth server not directly but transparently through your docker client when you pull (or push) an image from a docker image registry. The docker client is smart enough to actually store a copy of your username and password so you only have to login once to every registry you interact with. Docker stores this on Linux in the file ~/.docker/config.json.

~/.docker/config.json

{
    "auths": {
        "0.0.0.0:443": {
            "auth": "c2VjcmV0Cg==",
            "email": "[email protected]"
        },
        "0.0.0.0:5000": {
            "auth": "c2VjcmV0Cg==",
            "email": "[email protected]"
        },
        "https://index.docker.io/v1/": {
            "auth": "c2VjcmV0Cg==",
            "email": "[email protected]"
        }
    }
}

Let's suppose you want to write an application that let's you browse your docker image registry which is protected with JWT tokens. Below I discuss some of the implications this has.

How the auth server fits in

Since your docker image registry is configured to require a JWT token, you need to login to the auth server with your username and password and query if you have the required permissions to access the resource in the docker registry. The auth server then creates a token and signs it and you must hand it over to the docker image registry together with you actual request.

Token lifetime and cached credentials

Each token has an expiration or lifetime of some sort. To get a new token, one has to provide a username and a password to the auth server again. What if you want to go: hey, my token is about to expire in a minute, let's contact the auth server and prolong the token? Of course, the auth server currently requires as username and password and you won't actually prolong a token but instead get a completely new one. To achieve this however, you would have to cache the username and password used when making the first request to the auth server. In practice this is a no go!

Proposal

What if the auth server sends back not only the actual token we're going to hand over to the docker registry but also send us a (the client) a refresh token (https://auth0.com/blog/2015/10/07/refresh-tokens-what-are-they-and-when-to-use-them/ or https://auth0.com/docs/refresh-token) of some sort? Given such a refresh token, a client can request a new prolonged token without asking the user for a password on each request and without caching the credentials.

Storing refresh tokens on server side for invalidation/revocation of "sessions"

Through refresh tokens it is possible for an application to always have an unexpired token. This can be dangerous because no matter how short you set the expiration time of your normal JWT-token, the client will probably be able to artificially keep the lifetime as long as it wants.

If the auth server can keep track of the refresh tokens it has authored (maybe see #29 for this), then one can also implement a form of invalidation or revocation of refresh tokens. Just suppose that every refresh token being sent to the server is checked against a database and if it finds a match, the refresh token is considered okay; otherwise the refresh token has been effectively made unusable. (This can be compared to application specific passwords you authored in your Google or Facebook account.)

Final thoughts

What do you think of this idea? Do you see a use for this? I wrote the docker-registry-frontend and this is the use for myself. All in all the workflow won't break the communication between the docker client and the docker registry because the refresh token can be transmitted by the auth server in some X-header that is ignored by the docker client.

If you think this idea is good then I ask you to discuss whether a refresh token lets you query for a different repository or namespace than you originally asked for. In my opinion this should be possible; otherwise you'd need credentials again. Also, you might want to ask the auth server for access to more than one repository/namespace at a time. The problem right now is that the auth server doesn't support this kind of list-requests. But it is not required and an application probably can keep a token for each individual resource and refresh those individually as well.

kwk avatar Jan 13 '16 16:01 kwk

yes. frankly, the idea of storing plain text u/p on the client horrifies me. this is why i went for a temporary passwords for google auth - no way i'm going to store google account password in the clear. it basically already acts as such a token - despite being called a password. it has not expiration itself, just as oauth refresh token.

maybe we can generalize that mechanism?

rojer avatar Jan 18 '16 12:01 rojer

Hi, I see there is an option for offline_token=true to get access_token in spec[1], I do not see this is being supported by docker_auth. I guess it was added to the spec after? Thanks!

[1] https://github.com/docker/distribution/blob/master/docs/spec/auth/token.md

alonbl avatar Jun 03 '17 08:06 alonbl