OAuth2 and Open ID Connect – Part 1

Integrating with Thinktecture Identity Server v3

My current project is looking to use OpenID Connect (oidc) and OAuth2 for authentication and authorization.  We’ve decided to start out using the open source .Net implementation from Thinktecture. We’ve got to a point where we can authenticate and gain authorization from the identity server and call into a protected resource.  This article is an overview of what we’ve done so far.

Firstly you’ll need to have the identity server running.  I’m not covering how to get the identity server to connect to your own custom data store.  There are various interfaces you can implement to do this, but for now we’re just working with the in memory users ‘bob’ and ‘alice’ that come as part of the identity server git repo.  I opened the source in visual studio and started the host project which created an IISExpress site.  I put some breakpoints in the code and stepped through to get a feel for what is going on though if you just want to have the server running it’s quite nice to spin up IISExpress with the site from the command line rather than have the project open in visual studio.

The next thing I did was create a website with a sign in button which redirects to the identity server logon page.  At this point you’ll need to have some understanding of oidc and OAuth2.  Here’s the url I redirect to:

http://localhost:3333/core/connect/authorize?client_id=net2client&scope=openid%20profile%20read%20idmgr&redirect_uri=http://localhost:58276/SignInCallback.aspx&state=9e22ac8780a84497ad7707645d78dda9&response_type=id_token%20token&nonce=a68795f867a640a8909b9eff1cccc9c9&response_mode=form_post

Lets’ break this down and explain what it means.  The authorize endpoint is the part of the url without the querystring.  This endpoint performs the authorization and the querystring tells it what we want it to do.  Now for the querystring parameters.

  1.  The client_id is the id of the application requesting authorization.  Clients must be registered with the identity server and if a client_id which is not registered is received the request will be rejected.
  2. The scope value is a space separated list of values. openid is part of the oidc spec and indicates that we want to authenticate the user. The profile scope means we want access to the user’s profile. The read and idmgr scopes are resource scopes meaning that they are not part of the OAuth2/oidc spec but are defined by the resource (think api).  Both these scopes are defined in identity server and I’ve used them in my demo projects but they are custom scopes and would typically relate to your api functionality.
  3. The redirect_url is the url you want to be redirected to once authentication and/or authorization has taken place.  The redirect url must be registered with identity server as part of the client and multiple urls can be specified.  This feature means that malicious requests with evil redirect urls will be rejected.
  4. The state parameter is a unique value which is generated and sent as part of the request.  When the redirect occurs it will be passed back and the client should check that the response it receives contains the same state value that it sent to the identity server.  If it doesn’t it shouldn’t trust the response from the identity server.
  5. The response_type here is ‘id_token token’.  The id_token is part of oidc and is a feature which provides authentication in a way which OAuth2 does not.  See section 10 (esp 10.16) in RFC6749.  Essentially a valid id_token is proof of authentication and not just of authorization to a user’s profile. The token part means that we’re requesting an access token rather than an authorization code (in which case the value would be code).  This means that we are initiating the OAuth2 implicit flow typically used by browser based clients.  Server side clients would normally request an authorization code which would be sent to the browser and in turn to the server which would then exchange the code for an access token.  The purpose of the authorization code is to prevent the access token itself from being sent to the browser where it can be easily read and potentially misused.
  6. The nonce (number used once) parameter will be encoded in the id_token.  When the id_token is received back the client should check the nonce value it contains matches what was sent in a similar way to the state parameter.  This enables the client to ensure it does not accept an id_token which was not intended for it.
  7. Finally, the response_mode of form_post instructs the identity server to cause the tokens to be received by the client as part of a form post.

Once we’d registered our client and its redirect url with the identity server we could redirect to the authorization url as above and receive an id_token for authentication and an access_token for authorization.  Just to make things more interesting the first project where we’ll be using Oauth2 is an existing .Net 2.0 web application which was delivered to work in IE6.  Whilst IE6 compatibility would be hard to defend in 2014 it’s still a conversation that needs to be had and for the time being rules out handling the tokens in client side javascript.  There don’t appear to be any JWT libraries which are compatible with .Net 2.0 so we can’t handle the tokens there either.  So we’ve had to get a bit creative.

The request we made to the identity server will result in two tokens being returned, an id token for authentication and an access token for authorization.  It turns out that identity server can help us out with the access token as it has an access token validation endpoint which can accept the access token and return an unencrypted version which can be read with json.net in .Net 2.0.  However identity server will not validate the id token for us, we must do that ourselves.  So we created a webAPI project with a controller which can accept the signed id token, validate it and return the claims as json.  This api is not public facing and will be deployed on the same server as the client to keep things private.  Just to be clear, if you’re not working with a .Net 2.0 project you don’t need to have a separate service to validate the id token, so things are actually simpler.

So now we’re in a position where the client knows what claims have been authorized and it can ensure these are respected within the website. However it will also need to access the resource server which hosts some APIs we’ll be calling.  We have the authorization token we need to pass to the resource server api so next we needed to make sure that the api was secured so that it would only allow access to authorized resources.

For this we copied the SampleAspNetWebApi from the Thinktecture samples.  This is a basic web api project using Owin which introduces the Thinktecture.IdentityServer.v3.AccessTokenValidation authorization into the pipeline.  This library takes the claims from the supplies access token and adds them to a ClaimsIdentity which is set in an AuthenticationTicket.  This allows us to enforce authorization for controller actions decorated with the Authorize attribute.

In summary, this article has introduced the high level workflow involved in gaining access to an API secured with OAuth2 and OpenId Connect.  Our specific scenario also introduced the need for a separate service to validate the id token though for the majority of applications this won’t be necessary as you’ll be able to take advantage of the .net 4.5 JWT libraries.

In the next article I’ll introduce the demo projects we created to implement the workflow described here.

Advertisements

About maz100

I'm interested in the music called jazz, photography, my wife and two daughters, food, wine, software design and furniture...to name but a few.
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s