Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manual issuing of (unlimited) access tokens #105

Closed
256dpi opened this issue Oct 4, 2016 · 7 comments
Closed

Manual issuing of (unlimited) access tokens #105

256dpi opened this issue Oct 4, 2016 · 7 comments
Labels
feat New feature or request.

Comments

@256dpi
Copy link
Contributor

256dpi commented Oct 4, 2016

I'm working on a CMS like application that uses fosite to implement OAuth2 for all authentication and authorization purposes. The app uses the "implicit grant" for user authentication and the "client credentials grant" to authenticate applications that access data from the system (non web).

Now I would like to implement a feature that a SPA can directly access data and images from the CMS over an API. For that I would like to generate a long-lived access token that the application can directly use to access the data without having to authenticate and authorize itself. This is also important for caching images properly, etc.

As far as I can tell is the Access Token Lifespan configured on a global level (not per access token) this means that supporting unlimited access token would currently require to set the global token lifespan to infinite (very bad for security) or always returning an up to date RequestedAt time when loading the token from storage.

Is there a proper way implemented to handle this?

Following that I was also thinking about what would be the proper way to manually issue access tokens without talking to the database directly?

@aeneasr
Copy link
Member

aeneasr commented Oct 4, 2016

Hey, awesome that you ask this! I am working on a proposal to implement API keys which are bound to clients and basically long living OAuth2 access tokens in hydra: ory/hydra#234

I am completely open to have this proprietairy flow included in fosite if it suits your purposes.

The second option is to use a session struct that implements HMACSessionContainer where you can set the expiry time on a per-token or per-code basis. Unfortunately, this isn't currently implemented for JWT sessions.

@aeneasr aeneasr added feat New feature or request. question labels Oct 4, 2016
@aeneasr aeneasr added this to the fosite-hackday milestone Oct 4, 2016
@256dpi
Copy link
Contributor Author

256dpi commented Oct 4, 2016

Ok, cool :)

So, all the OAuth2 handling is part of a framework that I extracted out of this CMS project.

The following function authorizes the request:
https://github.com/gonfire/fire/blob/master/oauth2/authenticator.go#L140

And the authorization will at some point fetch the access token here:
https://github.com/gonfire/fire/blob/master/oauth2/storage.go#L110

As far as I can tell, one would need to configure the HMACSessionContainer and the token lifespan in the first function, yet the information that this token is in fact a long-lived token would be only available by the end of the second function. Is the proper way to reconfigure the session from within the second function on the storage?

@256dpi
Copy link
Contributor Author

256dpi commented Oct 4, 2016

The most natural way would be to set the expiry on the Requester returned by the lookup function:
https://github.com/gonfire/fire/blob/master/oauth2/storage.go#L141

At that point I'm asking myself: Why is the RequestedAt saved of a token and not the expiry date?

@aeneasr
Copy link
Member

aeneasr commented Oct 4, 2016

Sorry, I'm not enough in the mindset of your code, but if you don't know that the token will be long living when fosite is storing it in the database, you probably must override the database entry yourself :/

At that point I'm asking myself: Why is the RequestedAt saved of a token and not the expiry date?

The original idea behind this was to prevent people from issuing long living access tokens, as they are an anti pattern and one should use refresh tokens to achieve the same effect. However, after some time I was convinced by someone that this is a key feature so I introduced it as part of the session without breaking backwards compatibility and without compromising the way things usually work. Another part of the reasoning was that some (additional or proprietairy) requests might not have an expiry time at all so the base type should not have a mandatory ExpiresAt key which might not even do anything.

However I agree that this is a quirky part of the library.

@aeneasr
Copy link
Member

aeneasr commented Oct 4, 2016

One of the reasons for trying to prevent this is that people tend to use the implicit flow, then realize that it doesn't issue refresh tokens and then just say: oh ok, let's create access tokens that are valid for 30 days. But being imperative isn't always the right path for a library :/

@256dpi
Copy link
Contributor Author

256dpi commented Oct 4, 2016

Ok, I see the reasoning behind the RequestedAt and expiry time.

I'm still not sure where I need to configure/modify the HMACSession. The following storage method is called by fosite upon validating a newly received access token:

func (s *storage) GetAccessTokenSession(ctx context.Context, signature string, session interface{}) (fosite.Requester, error) {
  // ...
  session.(*oauth2.HMACSession).AccessTokenExpiry = time.Now().Add(1 * time.Hour)
  // ...
}

Would that be the right approach?

@aeneasr
Copy link
Member

aeneasr commented Oct 6, 2016

That looks good, sorry for the delayed response!

@256dpi 256dpi closed this as completed Oct 10, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat New feature or request.
Projects
None yet
Development

No branches or pull requests

2 participants