*

OpenID Connect in a nutshell

Date: : Last modified:2013/03/03 identity, OpenID Connect , ,

When you read the OpenID Connect Specifications, you might feel a little bit intimidated. That’s because they are written in “spec language” and they deal with corner cases, etc.  Yet when you translate them into normal English and just concentrate on a “simple case”, it becomes quite simple. So, here we go! (OK, much of the text is the same as the original proposal written by David Recordon. It was mostly just a matter of tweaking some of the parameter names, etc.)

Making an OpenID Connect request

In order for the client to make an OpenID Connect request, it needs to have the following information about the server:

  • client identifier – An unique identifier issued to the client to identify itself to the authorization server.
  • client secret – A shared secret established between the authorization server and client used for signing requests.
  • end-user authorization endpoint – The authorization server’s HTTP endpoint capable of authenticating the end-user and obtaining authorization.
  • token endpoint – The authorization server’s HTTP endpoint capable of issuing access tokens.
  • user info endpoint – A protected resource that, when presented with a token by the client, returns authorized information about the current user.
  • check id endpoint – A protected resource that, when presented with an id token by the client, checks the signature and returns information about the user’s session. (Deleted 2012/3/3 : it may come back as a generic OAuth token introspection endpoint)

This information is either obtained by the client developer, having read the server’s documentation and pre-registered their application, or by performing Discovery and Dynamic Registration.

The client constructs a regular OAuth 2.0 request to obtain an access token.

To turn an OAuth 2.0 request into an OpenID Connect request, simply include openid as one of the requested scopes. The openid scope means that the client is requesting an identifier for the user as well as the authentication context. If you want user’s profile URL, name, and picture etc., you can add the additional scope: profile. The server (and user) may choose to make more or less profile information available to the client. If the client also wants the user’s email address, it should include the scope email. The same goes for address (address) and phone (phone).

For example:

GET /authorize?grant_type=token%20id_token&scope=openid%20proflie&
     redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com

While pre-registering your client with servers is not required, it’s likely that servers will have varying policies and requirements placed upon clients when it comes to accessing user information.


Receiving an OpenID Connect response

Assuming the user authorized the client’s request, the client will obtain an access token. The OAuth 2.0 access token response will typically include two parameters: access_token and id_token. The following information is encoded as a JSON object in the id_token:

  • aud (audience) – REQUIRED. The client_id that this id_token is intended for.
  • exp (expiration) – REQUIRED. The time after which this token must not be accepted.
  • sub – REQUIRED. A locally unique and never reassigned identifier for the user (subject). e.g. “24400320” or “AItOawmwtWwcT0k51BayewNvutrJUqsvl6qs7A4″.
  • iss (issuer) – REQUIRED. A https: URI specifying the fully qualified host name of the issuer, which when paired with the user_id, creates a globally unique and never reassigned identifier.
    e.g. “https://aol.com”, “https://google.com”, or “https://sakimura.org”.
  • nonce – REQUIRED. nonce value sent in the request.

The id_token parameter is a simple way to make sure that the data received by the client through the User-Agent flow (or other untrusted channels) has not been modified. It is signed by the server using the client secret that was previously established over a trusted channel. It is the concatenation of a base64url encoded signature description (the algorithm), a period (.), a base64url encoded JSON object,  a period (.), and a signature string. This encoding is called a JSON Web Token (JWT). Note that base64url encoding uses two different characters from base64 and no padding.

An authorization server MUST only issue assertions about user identifiers within its domain. The client MUST verify that the aud matches its client_id and iss matches the domain (including sub-domain) of the issuer of the client_id. The authorization server is responsible for managing its own local namespace and enforcing that each user_id is locally unique and never reassigned.

When the client stores the user identifier, it MUST store the tuple of the user_id and iss. The user_id MUST NOT be over 255 ASCII characters in length.

The client SHOULD verify the signature. If the client does not verify the signature, it MUST make a call to the check id endpoint to verify it.

ALL OF WHAT FOLLOWS ARE OPTIONAL. 


Accessing user information

The user info endpoint is a regular OAuth 2.0 resource that returns a JSON document when fetched via HTTP and passed an access token. The client constructs an HTTPS “GET” request to the user info endpoint and includes the access token as a parameter.

The response is a JSON object that contains some (or all) of the following reserved keys:

  • sub – e.g. “AItOawmwtWwcT0k51BayewNvutrJUqsvl6qs7A4″.
  • profile – URL of the End-User’s profile page
  • name – display name of the user, e.g. “Nat Sakimura”.
  • given_name – e.g. “Nat”.
  • family_name – e.g. “Sakimura”.
  • email – e.g. “sakimura@example.com”.
  • picture – e.g. “http://graph.facebook.com/sakimura/picture”.

The server is free to add additional data to this response (such as Portable Contacts) so long as they do not change the reserved OpenID Connect keys. (Note: there are more defined keys, but for the sake of brevity, I am omitting them.)


Discovery

When using OpenID Connect, it’s likely that the client will both have buttons for popular servers as well as a text field for user entry of an email address or URL. (OpenID Connect does not directly solve the “NASCAR” problem.)

The goal of the discovery and registration phase is for the client to obtain the server’s authorization endpoint URL,  token endpoint URL, a client identifier, a client secret, and the user info API endpoint URL. If the client has pre-registered with the server, then this information will already be known. Otherwise the client will have to discover them through Discovery.

  1. The user clicks a button on the client to select a server. In this case the client will have selected a set of preferred servers and thus already knows their authorization endpoint URLs (among possibly other things). The client may or may not already be pre-registered.
  2. The user (or a User-Agent acting on their behalf) enters a URL or email address. In this case, the client needs to perform discovery and determine if there is a valid server endpoint URLs.

Steps:

1) Parse the user input to find out if it is an email address or a URL. If it is email address, do nothing. If no scheme, assume https.

2) Create a canonicalized identifier called “principal” by reconstructing the various parts. For example:

https://joe.example.com -> https://joe.example.com/
example.com -> https://example.com/
joe@example.com -> joe@example.com

3) Extract the domain and make a Webfinger call  over TLS/SSL.

  GET /.well-known/webfinger
    ?resource=acct%3Ajoe%40example.com
    &rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer
    HTTP/1.1
  Host: example.com

  HTTP/1.1 200 OK
  Content-Type: application/jrd+json

  {
   "subject": "acct:joe@example.com",
   "links":
    [
     {
      "rel": "http://openid.net/specs/connect/1.0/issuer",
      "href": "https://server.example.com"
     }
    ]
  }

4) To obtain the specific endpoint URL etc., the client appends “/.well-known/openid-configuration” to the issuer, and GETs the issuer’s configuration file over TLS/SSL as follows:

GET /.well-known/openid-configuration HTTP/1.1
Host: server.example.com

The response is a JSON object that includes endpoint and other information. For example:

{
 "authorization_endpoint": "https://server.example.com/connect/authorize",
 "issuer" : "https://server.example.com",
 "token_endpoint": "https://server.example.com/connect/token",
 "token_endpoint_auth_types_supported": ["client_secret_basic", "private_key_jwt"],
 "userinfo_endpoint": "https://server.example.com/connect/user",
 "check_id_endpoint": "https://server.example.com/connect/check_id",
 "registration_endpoint": "https://server.example.com/connect/register"
 }

 


Unregistered clients and dynamic registrations

Regardless of the discovery mechanism used, the client may or may not already be registered with the server. Servers may have different policies about what data clients can access based on whether they’ve pre-registered (which generally includes agreeing to ToS) versus using a dynamic registration.

If the client does not have a valid client identifier and secret, it can make the following HTTPS “POST” request to the server’s registration endpoint URL (see Discovery) with the following REQUIRED parameters in JSON format as the POST body:

  • redirect_uris – The array of URLs the client is registering with the server for receiving OpenID responses.

For example:

POST /connect/register HTTP/1.1
Content-Type: application/json
Accept: application/json
Host: server.example.com 

{
   "redirect_uris":
     ["https://client.example.org/callback",
      "https://client.example.org/callback2"]
}

Before responding, the server should check to see if the redirect URL is pre-registered outside of this OpenID flow. If so, an error response should be sent. Servers will need to develop a policy to handle what happens when a redirect URL is pre-registered by a developer but has already been used to create dynamic registrations. This might mean, for instance, that new dynamic registrations with that redirect URI will result in an error but requests using existing dynamic registrations continue working until they expire.

To issue a dynamic association, the server includes the following response parameters as JSON:

  • client_id – The client identifier. This could change with each response, which is up to the server.
  • client_secret – The client secret. This should change with each response.
  • expires_at – The number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the client_id and client_secret will expire or 0 if they do not expire.
  • registration_client_uri – The uri to operate on this registration data.
  • registration_access_token – The access token to be used to access the registration_client_uri.

The client should store their dynamic registrations based off of the server’s token endpoint URL. With each dynamic registration, the client will store the client identifier, client secret, expiration time, user endpoint URL, supported flows, and user info API endpoint URL. The expiration time should be stored as an absolute time or an indication that it lasts forever.


As you can see, the basic web client flows for OpenID Connect are quite straightforward, and nearly as simple as those that were originally proposed.  While additional functionality can be used, such as requesting specific sets of claims rather than the default set, having these additional capabilities available for when they’re needed don’t make simple interactions any more complex for clients, which will vastly outnumber the number of OpenID Providers.

 

(Revision History)

  • 2012-01-20 Initial version
  • 2013-01-31 Changed user_id to sub to reflect the change in the specs. 
  • 2013-03-03 Deleted check_id endpoint. Updated discovery and registration to match with the current draft.

Ads by Google

関連記事

The identity layer

OpenID Connect is here! – An Identity Layer on the internet

Celebrate! OpenID Connect 1.0 Final is here! Aft

Read more

no image

NTT docomo now an OpenID Provider

The largest mobile operator in Japan, NTT docomo,

Read more

openlabs.go.jp

Japanese government went live with OpenID/AB

Japanese government went live with OpenID Artifact

Read more

no image

OpenID Summit in Den Hague, Netherlands (Nov. 21)

The OpenID Foundation is hosting an OpenID worksho

Read more

no image

OpenID Foundation Board Election Started

OpenID Foundation board election has started. I

Read more

no image

Approve OpenID Connect Implementer’s Drafts!

Hi. OpenID Conenct Implementer's Draft voting h

Read more

Entity, Identity, Privacy

Entity, Identity, Privacy

First of all, let me state an important assumption

Read more

no image

Supporting IMAP etc. poor-man’s way

There are multiple efforts that are going on to br

Read more

no image

BrowserID protects the privacy of your Web activity? Really?

So, BrowserID is buzzing. In general, browser help

Read more

no image

Call for nominations for the Kantara Initiative 2011 IDDY (IDentity Deployment of the Year) Awards

The call for nominations for the 2011 IDDY (IDenti

Read more

Ads by Google

  • http://profile.yahoo.com/Y2HDJR4JXJJ3OCKRVCATWITPXE Thomas

    Thanks Nat, this is very helpful.

    • http://profiles.google.com/sakimura Nat Sakimura

      Welcome. 

  • http://twitter.com/atom atom

    Good post Nat! It would be helpful if you clarified whether or not clients should verify the id_token and also call the user_info endpoint after receiving an assertion. 

    • http://profiles.google.com/sakimura Nat Sakimura

      I will. The client should verify the id_token by itself (if capable of doing crypto itself), or call check id endpoint to verify it. It does not have to call userinfo endpoint unless it wants more “claims.”

      • Breno de Medeiros

        It would be nice to emphasize this point more.

        • http://profiles.google.com/sakimura Nat Sakimura

          So, do you have any concrete text proposal? 

          • Amit

            What are we gaining by verifying the id_token ? To make the userinfo call, we anyways use the access token .

  • http://id.mitre.org/jricher Justin Richer

    This is a great summary, and I think it helps to clarify many of the moving pieces from the clients’ perspective. I think it’d be helpful to get something similar from a server side. “So you want to be an IdP?”

    • http://profiles.google.com/sakimura Nat Sakimura

      Or, would you like to write it? 

      • http://id.mitre.org/jricher Justin Richer

        This is when I should learn to keep my mouth shut. :)

  • Eric Sachs

    What about the client checking that the aud (audience) field is actually for this client, and not another one being replayed?

    • http://profiles.google.com/sakimura Nat Sakimura

      Yes. Preventing replay of id_token that was issued to someone else is important and that is why there is aud claim. Thanks for pointing out. 

      • Eric Sachs

        I noticed the addition of the sentence ”
        The client MUST verify that the aud matches its client_id and iss matches the domain (including sub-domain) of the issuer of the client_id.”  That addresses my concern which John Bradley discussed in more detail at 
        http://www.thread-safe.com/2012/01/problem-with-oauth-for-authentication.html

        • http://profiles.google.com/sakimura Nat Sakimura

          Good! 

          We should promote John’s  post. 
          It is a public safety issue :-)

  • Pingback: OpenID Connect in a Nutshell | OpenID()

  • Pingback: Mike Jones: self-issued » OpenID Connect in a Nutshell()

  • Pingback: OpenID.net: OpenID Connect in a Nutshell « oracle fusion identity()

  • Pingback: Mike Jones – Microsoft: OpenID Connect in a Nutshell « oracle fusion identity()

  • Font

    At least part of the confusion comes from the terminology such as “Client” which is overloaded. For example, the service provider term of SAML roughly (but not exactly if you want to be pedantic) corresponds to Client; and IdP corresponds to server.

    • http://profiles.google.com/sakimura Nat Sakimura

      The terminology that I am using here is that of IETF OAuth 2.0., as that is the primary readership. 

  • http://arjam.net/rjmunro/ Robert (Jamie) Munro

    Could you add a paragraph at the beginning to say what OpenID connect actually is? Is it OpenID 3.0 with a cooler name, or is it fundamentally different? Assuming both the website and OpenID provider support it, what difference will a random non-technical user see?

    Something like “OpenID connect is the new version of open ID that in addition to letting you log in also …”

    • http://profiles.google.com/sakimura Nat Sakimura

      OpenID Connect is a new generation of the internet identity protocol. Technically, it is fundamentally different than OpenID 2.0. From the point of view of the non-technical end user, however, it would be hard to see the difference. 

      This article is written for the technical audience. There is a separate article for non-tech people at http://nat.sakimura.org/2011/05/15/dummys-guide-for-the-difference-between-oauth-authentication-and-openid/ . 

  • Pingback: mikael gourdon (mikaelgourdon) | Pearltrees()

  • Pingback: Adventures of an Eternal Optimist » Blog Archive » Time to Act!()

  • Pingback: Pamela Dingle – Ping Identity: Time to Act! « oracle fusion identity()

  • Pingback: Time to Act! « oracle fusion identity()

  • Pingback: OpenID Connect Webinar | Dazza Greenwood, JD()

  • Pingback: .blog » Archiv » Ohlédnutí za IETF 83()

  • Pingback: Litte - tvorba stránek » Ohlédnutí za IETF 83()

  • Pingback: Tech Stuff | Pearltrees()

  • Pingback: ste williams – OpenID Foundation launches XML-free ID handler()

  • Pingback: What's in a Name? Or a version number come to that - Smart421()

Ads by Google

Sato no aki
Autumn Greetings from Japan

Japan is now fully in Autumn. Leave

openid-icon-250x250
draft 02 of OpenID 2.0 to Connect Migration is now available

OpenID 2.0 to OpenID Connect Migrat

UMA-logo
Public Review of UMA 0.9 is going on

June 24: The three main UMA Version

CCS Injection
New vulnerability on OpenSSL found

A new bug in OpenSSL was found by M

no image
Covert Redirect is not new but.. A risk analysis and recommendations

So, there has been a flurry of worr

more...

PAGE TOP ↑