Jan 12th, 2012, 10:51 PM
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?
Jan 13th, 2012, 11:09 AM
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).
Jan 13th, 2012, 01:52 PM
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
Jan 14th, 2012, 04:18 AM
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.
Jan 15th, 2012, 03:02 PM
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:
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?
Jan 16th, 2012, 02:38 AM
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).