[Openid-specs-ab] About ID Tokens being access tokens

John Bradley ve7jtb at ve7jtb.com
Mon Aug 29 21:38:36 UTC 2011


As far as I know the token endpoint trades code for a access and refresh token,  or a refresh token for an access token.

There is no scope parameter for the token endpoint only the authorization one.

I think there is a basic requirement to be able to get the id_token to the RP via the redirect response, so it can start rendering a page before it makes the subsequent calls to the token and user-info endpoints.

John B.
On 2011-08-29, at 1:34 PM, Nat Sakimura wrote:

> Andreas,
> 
> I do not think OAuth sends 'scope' with Access Token Request. In the
> flow you describe, you are sending 'scope' with 'code' to the Token
> Endpoint. If it does, it can be used to exchange a one time access
> token 'code' to 'id_token' and 'access_token' on a separate call of
> the Token Endpoint as you describe, but I am not sure if we have an
> extension point there.
> 
> =nat
> 
> 2011/8/30 Andreas Åkre Solberg <andreas.solberg at uninett.no>:
>> On 26. aug.2011, at 20:27, John Bradley wrote:
>> 
>> An important issue for RP is perceived latency.  That is why they don't want
>> to have to do a extra round trip to get the id_token.
>> 
>> That is a very good argument.
>> 
>> If you have a JS client that needs an access token as well as a id_token it
>> would need to make two separate implicit calls to at the authorization
>> endpoint.
>> I suspect that is the biggest problem.
>> 
>> In the 'OAuth approach', there is no way of obtaining multiple tokens in the
>> implicit flow; the oauth approach would in this flow issue a multi-scope
>> token to the RP. This could make things much simpler to JS clients. It could
>> be a simpler and smarter way - or it could be a showstopper; anyone with
>> first-hand knowledge to the implicit flow use case that can elaborate a bit
>> on this?
>> Note that by issuing a multi-scoped token ( the OAuth way ) in the implicit
>> flow; we solve the issue mentioned earlier about the necessity to include a
>> hash of the access token in the id_token.
>> Actually in OAuth implicit grant flow, you are NOT allowed to return both an
>> access token and a refresh token; and I suspect that the reasoning behind
>> this is the exact same that we run into with id_token and access token.
>> 
>>  For a server it is also several round trips that each may require user
>> consent.  From a user experience point of view one trip to the OP is enough.
>> 
>> No, there is no additional front-channel round trips in the proposal.
>> Instead some backchannel calls are added to retrieve tokens, and id token +
>> user data.
>> 
>> We are running into a OAuth issue.  There should be a standard way to
>> request multiple tokens.
>> 
>> There is; (you may request multiple scopes in the request) and I'm
>> suggesting that we use it. What there is not, is a way to requset multiple
>> tokens and receive them all at the same time.
>> 
>> In the case where you only want code in the redirect, scope is about the
>> only place to say that you want a access token for the user-info endpoint
>> and a id_token returned from the token endpoint.
>> 
>> That was why I was proposing that the openid scope be about the id_token and
>> we define other scopes for user-info.
>> 
>> Great, that is a brilliant idea :) And this is also what I am suggesting :)
>> 
>> That way scope controls what tokens you want (perhaps others for portable
>> contacts etc), and response_type controls how you get them.
>> 
>> Exactly.
>> 
>> There was a proposal to the allow multiple access tokens to be returned by
>> making it an array or structure.
>> That didn't happen, so we are on our own to define how multiple tokens are
>> returned.
>> 
>> If we need them returned all at once.
>> 
>> That makes it more complicated to use standard libraries.    I don't think
>> we are the only ones with this issue
>> 
>> The other issue with treating a id_token as an access token is that some
>> frameworks don't make it easy to get at the contents of the token used to
>> authenticate to the endpoint.
>> I suspect that is going to be a problem with them using any sort of JWT as
>> an access token.
>> 
>> Yup. The response of the token endpoint is most likely handled all by the
>> OAuth client library, and it should follow the OAuth spec section 4.2.2:
>> The client SHOULD ignore unrecognized response parameters.
>> 
>> And I assume there it is a significant probability that these unrecognized
>> response parameters are accessilble through the client library API.
>> This also is pointing in the direction of beeing more streamlined with
>> OAuth.
>> Some arguments pro this approach:
>> * Simpler spec, easier to understand.
>> No confusion of what is a token, and is a 'token' to be decoded or used as
>> if it were an access token…
>> * Simpler to implement, more re-use of OAuth library.
>> Some arguments against this approach:
>> * Additonal back-channel calls to resolve tokens, and tokens to JWT.
>> * Potentially a showstopper with a multi-purpose token in the implicit flow?
>> Here is an example of how the flows may look like (I hope it do not include
>> too many errors):
>> 
>> Walkthrough of the OpenID Connect more streamlined with OAuth-Approach
>> 
>> Using the OAuth approach of obtaining two tokens (by the use of a refresh
>> token), we gain the flexibility of both having the user data token and the
>> session (id) token as two completely independent tokens; and in other use
>> cases (like in implicit grant) have a shared multi-scoped token for use on
>> both services.
>> 
>> Authorization Code Flow
>> 
>> Client prepares an authorization request:
>> 
>> GET /authorization?
>>    response_type=code&
>>    cliend_id=ab1&
>>    scope=openid-session%20openid-userdata HTTP/1.1
>> Host: rp.example.com
>> 
>> The user logs in, performs consent, etc. and the user agent is redirected
>> back to the RP with the following response:
>> 
>> GET /callback?
>>    code=BBB3330
>> Host: consumer.example.org
>> 
>> Obtaining an session access token, and getting the ID Token
>> 
>> The client uses the access token endpoint to resolve
>> an openid-session token:
>> 
>> POST /token
>> Host: rp.example.org
>> Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
>> Content-Type: application/x-www-form-urlencoded;charset=UTF-8
>> 
>> grant_type=authorization_code&
>> code=BBB3330&
>> scope=openid-session
>> 
>> The provider responds by issuing an openid-session access token, and also
>> an refresh_token.
>> 
>> HTTP/1.1 200 OK
>> Content-Type: application/json;charset=UTF-8 Cache-Control: no-store
>> Pragma: no-cache
>> {
>>    "access_token":"2YotnFZFEjr1zCsicMWpAA",
>>    "token_type":"bearer",
>>    "scope": "openid-session",
>>    "expires_in":3600,
>>    "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
>> }
>> 
>> Note: the openid-session access token is transparent and NOT an JWT. It may
>> be exchanged for a JWT using the check session service.
>> 
>> The provider obtains the ID Token using the openid-session access token;
>> performing a request to the check session endpoint; a basic OAuth protected
>> endpoint:
>> 
>> POST /check_session HTTP/1.1
>> Accept: application/jwt
>> Authorization: Basic 2YotnFZFEjr1zCsicMWpAA
>> Content-Type: application/x-www-form-urlencoded
>> Content-Length: 0
>> 
>> The provider returns an JWT (because of the Accept header, may also return
>> unsigned JSON):
>> 
>> Content-Type: application/jwt;charset=UTF-8
>> 
>> eyJpc3MiOi.Jqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogIm.h0dHA6Ly9le
>> 
>> And the returned JWT may be decoded (and validated) by the client to
>> something like:
>> 
>> {
>>  "issuer":"http://server.example.com",
>>  "client_id","http://client.example.com",
>>  "audience", "http://client.example.com",
>>  "user_id":"user_328723",
>>  "exp":1303852880
>> }
>> 
>> Obtaining an user data access token, and getting the user data
>> 
>> The client uses the already obtained refresh_token when accessing the OAuth
>> Token Service, and requests the scope openid-userdata:
>> 
>> POST /token
>> Host: rp.example.org
>> Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
>> Content-Type: application/x-www-form-urlencoded;charset=UTF-8
>> 
>> grant_type=refresh_token&
>> refresh_token=tGzv3JOkF0XG5Qx2TlKWIA&
>> scope=openid-userdata
>> 
>> The provider responds by issuing an openid-userdata Access Token:
>> 
>> HTTP/1.1 200 OK
>> Content-Type: application/json;charset=UTF-8 Cache-Control: no-store
>> Pragma: no-cache
>> {
>>    "access_token":"2YotnFZFEjr1zCsicMWpAA",
>>    "scope": "openid-userdata",
>>    "token_type":"bearer",
>>    "expires_in":3600,
>> }
>> 
>> The consumer, uses the OAuth protected user data endpoint to retrieve user
>> data:
>> 
>> POST /user_info HTTP/1.1
>> Accept: application/jwt
>> Authorization: Basic 2YotnFZFEjr1zCsicMWpAA
>> Content-Type: application/x-www-form-urlencoded
>> 
>> schema=openid
>> 
>> The provider returns an JWT (because of the Accept header, may also return
>> unsigned JSON):
>> 
>> Content-Type: application/jwt;charset=UTF-8
>> 
>> eyJpc3MiOi.Jqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogIm.h0dHA6Ly9le
>> 
>> And the returned JWT may be decoded (and validated) by the client to
>> something like:
>> 
>> {
>>    "id": "90125",
>>    "name": "Jonathan Q. Doe"
>>    "given_name": "Jonathan",
>>    "middle_name": "Q.",
>>    "family_name": "Doe",
>>    "nickname": "John",
>>    "email": "johndoe at example.com",
>>    "verified": true,
>>    "profile": "http://example.com/johndoe/",
>>    "picture": "http://example.com/johndoe/me.jpg",
>>    "website": "http://john.doe.blogs.example.net/",
>>    "gender": "male",
>>    "birthday": "05/02/0000",
>>    "zoneinfo": "America/Los_Angeles"
>>    "locale": "en_US",
>>    "phone_number": "+1 (425) 555-1212",
>>    "address": {
>>        "region": "WA",
>>        "country": "United States"
>>    },
>>    "last_updated": "2011-06-29T21:10:22+0000"
>> }
>> 
>> Implicit Flow
>> 
>> The consumer, performs an authentication request:
>> 
>> GET /authorization?
>>    response_type=token&
>>    cliend_id=ab1&
>>    scope=openid-session%20openid-userdata HTTP/1.1
>> Host: rp.example.com
>> 
>> The user logs in, performs consent, etc. and the user agent is redirected
>> back to the RP with the following response:
>> 
>> HTTP/1.1 302 Found
>> Location:
>> http://consumer.example.org/callback#access_token=2YotnFZFEjr1zCsicMWpAA
>> &scope=openid-session%20openid-userdata&state=xyz&token_type=bearer&expires_in=3600
>> 
>> Then the consumer got an Access Token that is valid at both the User Data
>> service and at the Session Service.
>> 
>> The user agent may send the access token to the web protected resource, and
>> the web protected resource will use the access token with both the user info
>> and session info service.
>> 
>> _______________________________________________
>> Openid-specs-ab mailing list
>> Openid-specs-ab at lists.openid.net
>> http://lists.openid.net/mailman/listinfo/openid-specs-ab
>> 
>> 
> 
> 
> 
> -- 
> Nat Sakimura (=nat)
> Chairman, OpenID Foundation
> http://nat.sakimura.org/
> @_nat_en

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4767 bytes
Desc: not available
URL: <http://lists.openid.net/pipermail/openid-specs-ab/attachments/20110829/64f38f02/attachment.p7s>


More information about the Openid-specs-ab mailing list