Page 1 of 3 123 LastLast
Results 1 to 10 of 21

Thread: using s2-oauth provider for sign-on: one-time grant prompt and returning same token

  1. #1
    Join Date
    Jul 2005
    Posts
    111

    Default using s2-oauth provider for sign-on: one-time grant prompt and returning same token

    i'm working on a project where we are trying to implement an oauth(2) provider that can be used for sign-on.
    for example, a tonr-ish client might have a button labeled 'sign on using your sparklr-ish account',
    and when you click it, it does the oauth dance:

    (a) prompts you to sign on to sparklr-ish
    (b) prompts you to grant access to sparklr-ish resources
    (c) gets an auth code and exchanges it for an access token
    (d) uses that access token to get a 'user profile' resource with some basic info (first name, last name, username), this basic premise is captured by spring-social

    so far, so good.

    for this sign-on-using-oauth-provider pattern, we might logout of tonr-ish (having not made any attempts to persist the access token), come back the next day and click the 'sign on using your sparklr-ish account'.

    the desired effect is that:

    (e) the user is prompted to sign on to sparklr-ish
    (f) the user is not prompted to grant access again since they already did this previously
    (g) the client gets an auth code and exchanges it for an access token (i think it should be the same access token that was provided the previous day, just so the provider isn't stacking up a new access token in it's database for each of multiple logon events)
    (h) the client gets the 'user profile' resource using the access token and does whatever 'account joining' activities it cares to do in terms of reconciling the tonr-ish login session with the sparklr-ish user-profile.

    so my questions are generally:

    - has anyone successfully accomplished anything like this with s2-oauth?
    - if so, any tips?
    - is there anything about s2-oauth that would make implementing this behavior cumbersome?
    - any other recommendations or thoughts on the topic?

    thanks,
    tony.

  2. #2
    Join Date
    Jun 2005
    Posts
    4,231

    Default

    I have implemented such as system, and it seems to work OK. It's basically the way that the OpenID Connect standard works (http://openid.net/specs/openid-conne...rd-1_0-07.html). We might even support some form of the standard in Spring Security at some point if they get the spec finished.

    I'm quite interested in your points about token persistence, and I think they would bear some more analysis. If you find that the framework stores more tokens than necessary, then we could work on fixing it.

    Remembering past approvals is not a feature of the framework as it stands, but you may find that normal cookies and servlet sessions have the desired effect anyway. It's not really covered in the spec, and it seems that any practical implementation would be limited by the servlet session expiry anyway (or other persistence if you changed the authentication storage strategy in Spring Security).

  3. #3
    Join Date
    Jul 2005
    Posts
    111

    Default

    hi dave,

    appreciate the response.

    i'm familiar with open-id, but not open-id-connect.

    scanning the link you sent, it seems that is exactly what i am after,
    but it also indicates that plain-old-oauth doesn't really cover the authentication use case all by it's lonesome.

    generally, it seems like oauth expects the client to hold on to the token after a single dance,
    but the authentication case leads us to invoke the oauth-dance for each login, so therein lies the rub.

    the desired effect from the provider is that when a client-user initiates the oauth-dance (as it will for each login),
    prior to prompting the client-user for a grant, the provider looks in it's database to see if a token has already been issued to this client-user, if so (and it hasn't expired), the grant prompt should be skipped and the some token should be issued to the client-user (or minimally the existing token-row should be updated with a new token, or deleted prior to adding a new token-row) this will avoid token-row creep with each login event.

    do you think s2-oauth can be 'hooked' in such a way as to gain the desired effect?

    i wouldn't necessarily expect the out-of-the-box jdbc implementations to behave this way,
    but it would be cool if the interfaces supported this behavior with customized implementations.

    if this use-case wasn't on your (and/or ryan's) radar when you designed the interfaces, there may be some modification required at that level. for instance, i think we would need the ability to:
    (a) allow for a way to lookup a token based on client-user, and
    (b) skip the grant prompt

  4. #4
    Join Date
    Jun 2005
    Posts
    4,231

    Default

    I think the point of OpenID Connect is not to extend OAUth2 where it has missing features per se (but there are extensions on the table) - it is really just defining a set of standard endpoints and scopes for exchanging user profile data using the existing protocol. So I don't necessarily agree with your statement that authentication can't be handled with vanilla OAuth2 (which is what you get out of the box with Spring Security OAuth at the moment).

    I don't think the token service APIs need to change, and like I said I already have a system working. It should be in production next week (light load to start with). Skipping the grant prompt is a decision the client app has to take, so maybe that's the link with the UserDetails you were asking about - if you look at the OpenID support in Spring Security you can see that there is a UserDetails component, and it is up to the client app to decide how much data to store and for how long. Recent snapshots will skip the grant prompt automatically if all the data is in the authorization code request, but even in older releases all you need to do is provide a custom user approval page.

  5. #5
    Join Date
    Jul 2005
    Posts
    111

    Default

    i didn't mean that authentication couldn't be handled with vanilla oauth2, i meant that the spec doesn't explicitly cover that use case
    (and that's where something like openid-connect can add value w.r.t. standardization).

    w.r.t. your app, not sure how much you can disclose, but do you control both the client and provider, or just one of the two?

    in my particular case, we currently have spring-social at the client and s2-oauth (m4) at the provider.

    i'm sure it's (at least partially) me, but i'm confused about the client handling the skipping the grant prompt.

    trying to follow the flow with tonr/sparklr using the network panel in chrome developer tools, i witness something like:

    (1) /tonr/sparklr/photos->302->/sparklr/oauth/user/authorize->302->/sparklr/login.jsp

    (2) /sparklr/login.do->302->/sparklr/oauth/user/authorize->302->/sparklr/oauth/confirm_access

    so it never returns control to /tonr before it 302's to the confirm_access.

    how would a client (e.g. spring-social in my case) be responsible for the grant prompt decision using this flow?

  6. #6
    Join Date
    Jun 2005
    Posts
    4,231

    Default

    On the server you can set the userApprovalPage to forward (instead of redirect) to a controller that handles the authorization itself, instead of prompting the user. That would always work. Since last week if you control the client and the server you can also get the client to send oauth_user_approval=true along with the other authorization request stuff. If Spring Social can't be modified to do that I will be surprised, but I haven't tried it myself (my apps all use Spring Security OAuth on the clients).

  7. #7
    Join Date
    Jul 2005
    Posts
    111

    Default

    cool! learn something new every day...

    can you confirm my understanding:

    (1) set provider-side to use forward (v redirect) for userApprovalPage:
    - so this gives me a provider side controller hook to determine whether to display the consent page
    (still provider side decision v client side yes?)

    (2) have client pass oauth_user_approval=true to have provider skip consent page
    - the client would need enough information about the user to know whether to set this to true or false,
    but in my particular case, the client doesn't know who the user is until it can successfully login to the provider,
    obtain an access token and call back in to the oauth provider for some user-profile information. so it seems like this hook won't work for me, but i can't help feeling i'm missing something...

    thx,
    tony.

  8. #8
    Join Date
    Jun 2005
    Posts
    4,231

    Default

    Your replay sounds about right. I haven't tried authentication with automatic approval, nor have I tried it with Spring Social, so I can't really comment in detail on that right now. But I don't see why you need to know who the client is to send the oauth_user_approval=true flag (you just want to be sure that your user really does approve - presumably if the scope is narrowed to retrieving user info for the authentication it's easy to argue that any user would approve).

  9. #9
    Join Date
    Jul 2005
    Posts
    111

    Default

    ok, i see what you are saying about potentially unconditionally having the client flag the provider to skip the consent prompt.

    i was thinking that we would want to obtain consent the first time through, in which case, if the client knew the user, it could determine if the user had been through the handshake once and conditionally pass the flag.

    did you say you were working on an application that uses s2-oauth for authentication purposes?

    if so, how does your version of this pattern manifest? (e.g. does it unconditionally prompt for consent each time the same user logs in?)

    my other concern, which is perhaps tangential to the consent prompt, is that the provider not unconditionally construct a new token each time the client-user logs in, but rather checks the provider side token store to see if this client-user has already been granted a token and if so, just returns the existing one (or the other variants i itemized that result in only one token per client-user in the provider side token store).

    it looks like that can be accommodated though cause the signature of TokenStore.getAccessToken() takes an OAuth2Authentication reference which includes an Authentication reference which (i think) should have the actual user info in it (not just the client), so an implementation of TokenStore should be able to enforce the behavior i'm describing. does this sound correct?

  10. #10
    Join Date
    Jun 2005
    Posts
    4,231

    Default

    Quote Originally Posted by tony_k View Post
    if so, how does your version of this pattern manifest? (e.g. does it unconditionally prompt for consent each time the same user logs in?)
    It prompts a lot. At the moment we rely on cookies to store enough state to prevent the confirmation becoming annoying, but I can see where you are going with the token persistence below (hence I added some features). If you could try it out you might find the right direction to start slicing to provide that feature better (there is also a relevant JIRA ticket https://jira.springsource.org/browse/SECOAUTH-129).

    my other concern, which is perhaps tangential to the consent prompt, is that the provider not unconditionally construct a new token each time the client-user logs in, but rather checks the provider side token store to see if this client-user has already been granted a token and if so, just returns the existing one (or the other variants i itemized that result in only one token per client-user in the provider side token store).

    it looks like that can be accommodated though cause the signature of TokenStore.getAccessToken() takes an OAuth2Authentication reference which includes an Authentication reference which (i think) should have the actual user info in it (not just the client), so an implementation of TokenStore should be able to enforce the behavior i'm describing. does this sound correct?
    Yes. And I think the existing *TokenServices now support this out of the box (since yesterday) - you might have to provide an OAuth2AuthenticationKeyGenerator, but the default is probably fine.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •