Comments (22)
I like the block approach! I need to configure the expiration time per consumer (infinite expiry for iphone and 2 hours for web), so this approach would solve my problem, too.
from doorkeeper.
So - I want some kind of dynamic configuration to override the determination of the expiration time in run time (like Facebook's offline_access), which then supports 0 or some kind of special value to mean "never expires". What do you think?
@miyagawa Please do not implement a feature like that with no expiration time. Expiring access tokens is a security feature... Not expiring them opens applications to attack. In mobile apps most of all since the access token is actually user accessible and not passed on back channels between two web servers.
Instead you may want to investigate implementing an offline_access feature via a scope. If a client has that scope it should be able to request a new access token with a refresh token even if the user doesn't have a current session.
You may also want to look at the OpenIDConnect Spec and in particular the section on Offline Access.
from doorkeeper.
Can we open this issue again?
I need different expiration times for different resource owners or applications, say 10 hours for admins and 2 hours for normal users, just as @felipeelias demonstrated.
Please do not implement a feature like that with no expiration time.
This issue is, in my eyes, not primarily concerned with unlimited expiration time. I agree that that would not be good.
However, the block approach would allow for different expiration times for different users and/or applications rather than one for all. I can e.g. imagine the user checking a checkbox at login saying "This is a public computer, my token should only be valid 10 minutes just for this session" or something like that.
Or, say, 1 hour on mobile devices but 10 hours on desktop clients.
from doorkeeper.
@mmzoo Are you trying to use access tokens for session management? I urge you to please not.
Since access tokens should only be used to determine if a client application has authorization to act on the user's behalf it shouldn't matter how short the access tokens live. The client application can (and should) refresh their access token as needed to continue their authorization to user data (if the provider can determine the user still gives their consent).
Whether or not the user has a session is up to the client to determine. That maybe using by using an access token to get some data back from the provider or another service. But the token itself shouldn't be an indicator of having a session. IMHO, anything more than about 10 minutes is an irresponsible amount of time to let an access token be considered valid. According to section 5 of the OAuth 2 spec, access tokens should live < 1 hr.
Issue short-lived bearer tokens: Token servers SHOULD issue
short-lived (one hour or less) bearer tokens, particularly when
issuing tokens to clients that run within a web browser or other
environments where information leakage may occur. Using
short-lived bearer tokens can reduce the impact of them being
leaked.
I need different expiration times for different resource owners or applications, say 10 hours for admins and 2 hours for normal users
Can you talk some about your specific use case? There's probably another way to tackle the same thing that doesn't not involve leaving user data open to unauthorized access.
from doorkeeper.
@mmzoo Do you have an email I can send a response to? I have some ideas and suggestions from what I've built in the past to handle use cases like auto sign in, auto sign out, handling access tokens when a user changes credentials, knowing about session across applications, etc. I've built and thought about all of it before and would love to discuss with you but hate to fill this issue with our implementation details.
Some brief details:
Option 1: Shared data store
I know there was an assumption that this is not the case, but if it's a possibility and all the clients will be behind a firewall it may make sense... This won't help if a 3rd party app or a mobile app needs to know about the session, but it's an option. I haven't gone with this option in the past for those very reasons so I'm not confident I can think out all the pros and cons but some are apparent (having to be behind the firewall, availability of the data store, etc.)
Option 2: Session state
One generic suggestion would be to have the provider calculate an opaque session_state
value that is sent to the client along with the user's information. This session_state would be recalculated every time there's a change to their session's status. The client can hit an endpoint sending the session_state
it knows about to the server and the server can respond with whether or not the state is still valid. If it's not valid the client can end the user's session and perform another handshake with the server to determine whether or not the user is currently signed in. How you store it, when you send it to the provider to determine the session status, etc. is kind of out of scope and hard for me to advise you in with out more intimate knowledge of your specific use case and needs... But generically, that's one way to do it. As far as making sure the client app I authorized to that information, you could do something like the client credentials flow.
There's even more ideas in the OpenID Connect Session Management spec. OpenID Connect is primarily an identity layer on top of OAuth 2 but there's also some good ideas in there for how to handle different use cases like yours.
from doorkeeper.
I'm looking for this feature as well.
Doorkeeper devs, if I submitted a pull for this feature with accompanying specs, would you be open to accepting it?
from doorkeeper.
@mattgreen we'll be open to accept it :-)
@miyagawa we thought about it, we just didn't implement because of the specs, but it is very requested feature.
I think some dynamic configuration would help. Maybe we should use the same idea of #70? This way you could configure the expiration depending on resource owner/client/scope or others.
Thoughts?
from doorkeeper.
What if we used a config block, much like resource_owner_authenticator
? I can imagine the block accepting two parameters: the resource_owner, as well as the token. Additionally, perhaps it could be used to signal that a token should not be issued; say, by raising a specific exception.
By doing this, you could enforce odd requirements, such as "only one access token issued per x days", etc. It's tricky to know where to draw the line in terms of a sane level of configuration.
from doorkeeper.
@mattgreen not sure if this would be the exact place to handle the case for "only one access token issued per x days". I like the idea though.
This will be something like a decision of the expiration time based on some parameters, few use cases:
- If the request has a specific scope, like
offline_access
, then returnnil
as expiration time - If the client (or resource owner) has an specific attribute or permission (maybe "admin" client)
So we could use a block like:
access_token_expiration do |client, resource_owner, request|
if request.scopes.include? :offline_access
nil
elsif client.admin?
10.hours
else
2.hours
end
end
# and then, during token creation
Doorkeeper.configuration.access_token_expiration.call(client, resource_owner, self)
# => 2.hours (for example
Not sure if this would be the best way to handle this, I'd love to hear some thoughs.
from doorkeeper.
Just started an experimental configuration for this on this branch: https://github.com/applicake/doorkeeper/compare/dynamic-expiration
from doorkeeper.
π for the block approach as well.
from doorkeeper.
This is exactly what I am looking for. Is there anything I can do to help?
from doorkeeper.
was something like this ever implemented?
from doorkeeper.
My use case was specifically web apps as client where credentials can be
saved securely. Anyway I stopped using doorkeeper at this point.
from doorkeeper.
Default expiration time can be configured in
doorkeeper/lib/doorkeeper/config.rb
Line 176 in 84f809a
from doorkeeper.
@niftyn8 I appreciate your commitment very much, thank you :) Yes, I seek to implement a single-sign-on architecture with "server side session authentication" and found that, if I were to build that from scratch, it would look like OAuth.
My use case
I have the client applications alpha.dev
and beta.dev
etc. and the doorkeeper server doorkeeper.dev
.
My goals are
- The end user can seamlessly switch between
alpha
andbeta
without having to log in twice - The end user can logout of all client applications with one click
- The end user has an overview of all ongoing sessions, just like Github has in your account settings, and can remotely invalidate them
A few conditions/assumptions are given
- I have full control over every application (except, say native mobile client apps where secrets and traffic can be forcibly extracted)
- All traffic is TLS encrypted
- There is no shared data store, if any application wants to talk to another, it has to be via API requests
- Every client app is a separate OAuth Doorkeeper consumer, that is, a token of one app cannot be abused for another app
My suggested solution is
- When logged in in
alpha
, there is some form of unique token in the local cookie - At every request (or, at least rather frequently), I let
alpha
validate that token against the list of sessions atdoorkeeper.dev
(say, via requests signed with that token to avoid actually sending the token over the wire again and again) - With that request to
doorkeeper.dev
I can also update the latest session activity and retrieve the current set of authorization rules for that user
My thoughts are
- The Doorkeeper gem basically already provides that architecture
- Everybody says OAuth access tokens should be short-lived to prevent misuse of leaked tokens (and I agree), but is a cookie not a long-lived shared secret as well? I guess it's not passed around that much though...
- Heroku solves this via a cross-subdomain cookie, but I don't have the same TLD so I cannot do that
- Github can maintain the sessions sever-side because there is (AFAIK) just one application, not
alpha
andbeta
like in my case
access tokens should only be used to determine if a client application has authorization to act on the user's behalf
This is true. But let's take the simple example of the user changing the password (which only the server is aware of) because the user feels that it might have been stolen. I want to stop the client application from acting on the user's behalf immediately.
The client application can (and should) refresh their access token as needed to continue their authorization to user data
So you want me to ensure some sort of access token rotation by using refresh tokens? I just felt a little awkward sending refresh tokens over the wire basically all the time. But then again, I see your point. If someone steels my cookie it would only be valid for a very short time.
If that's all then I can implement that! :) It would cost me an additional round-trip though in case the access token timed out. I don't feel it's ideal that that could happen at every request, but I could live with it if it's more secure.
Whether or not the user has a session is up to the client to determine
Yes, but in the case of SSO it should be up to the server, not the client.
But the token itself shouldn't be an indicator of having a session
I thought this was a practical thing to do in my use case. Actually, I believe that having some sort of shared token between the client and the server is the only
way to implement this. May it be either a rolling token or a long-lived one.
But, to summarize: The major problem you see is that leaking a token gives evil people access for too long time? What if I roll the token every minute using a refresh token? And would it not be even more secure to never send tokens over the wire by just signing the requests instead of sending the actual tokens? I could keep a separate, public session identifier around so that the server knows which access token to validate the signature against...
from doorkeeper.
@niftyn8 @mmzoo would love if you guys could loop me in as well (ksheurs at gmail). i've been looking to build something very similar. thank you!
from doorkeeper.
@niftyn8 Brilliant. My thoughts were actually progressing into exactly that direction (session state) but you were some steps ahead of me :) I was just creating a sessions table in my doorkeeper app to keep track of those...
You can reach me via ssoπ©posteo.ee so we don't have to spam this thread :)
Thank you doorkeeper.
from doorkeeper.
This is a great discussion guys, please move on in a Github issue/wiki instead of on private email! π
from doorkeeper.
It turned out that the discussion moved around over here for those interested.
from doorkeeper.
Also checkout the projects and talks of @jagthedrummer, he's been doing quite a good job on this (and presenting in conferences). π
from doorkeeper.
Thanks for the mention, @tute! Here's a link to a bunch of resources for a talk I gave at RailsConf about using doorkeeper for SSO.
UPDATED : I forgot to include the link. π€¦
http://www.octolabs.com/blogs/octoblog/2014/04/22/service-oriented-authentication-railsconf/
from doorkeeper.
Related Issues (20)
- How do I know if an application has been authorized by a resource owner? HOT 1
- Regression with Errors in 5.6.8 HOT 5
- Refreshing a token sending scopes separated by `+` does not work HOT 5
- Cleanup job removes not expired tokens HOT 1
- Different access grants return the same access token with `reuse_access_token` enabled
- Removing active_record_options was a breaking change HOT 1
- `Doorkeeper::AccessToken.find_or_create_for` with empty scopes raises NoMethodError HOT 6
- Token revocation error when token contains null byte. HOT 2
- Doorkeeper is loading ActiveRecord too early HOT 1
- AuthorizedApplications returns the date that the _application_ was created, not the date that the _authorization_ was created HOT 2
- Add GitHub Discussions to the project HOT 1
- Doorkeeper appears to be missing a way to validate client configuration before redirecting to the authentication page HOT 1
- Access tokens should be revoked when multiple attempts are made to exchange the same authorization code
- When introspection is disabled we return 200 for authorized clients via basic auth but 401 for authorized clients via bearer auth HOT 8
- Option to specify supported PKCE code_challenge_methods supported HOT 7
- Doorkeeper's redirect_uri validation is not implemented according to specification
- Refresh Tokens as-implemented are susceptible to Refresh Token Reuse Attacks
- Support for RFC 9207 - OAuth 2.0 Authorization Server Issuer Identification
- Issues getting tests running HOT 3
- Doorkeeper shouldn't generate a secret for public clients HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from doorkeeper.