Introduction to OAuth2 part 6: issues

Introduction

OAuth2 is abound in the world of mobile applications, but it has drawn some criticism as well regarding its usefulness and security. A lot of it originates from Eran Hammer who originally led the specification committee of OAuth2.

Specification too wide

The OAuth2 specs started out as a protocol called Web Authorization Protocol. A protocol is a strict set of rules and definitions. All organisations that adhere to a protocol will be interoperable with each other. As OAuth2 was gaining ground more and more companies wanted to take part in the discussions and have their say. As you may certainly know as the number of participants around a topic grows the more difficult it will be to reach an agreement with a concise set of rules. Instead all parties enforced their own little modifications and company-specific enhancements and alternatives. After a while OAuth2 could not be regarded as a protocol anymore as it became too generic.

At that point the protocol was renamed the OAuth2 Authorization Framework. In effect it was a framework of protocol subsets. You can make a quick search in the specification document here. Search for the words ‘may’ and ‘should’. At the time of writing this post they appeared 69 and 75 times respectively: ‘The client should avoid’, ‘authorization server may establish’ etc. Those verbs only denote the possibility of an action, not that it is obligatory, i.e. ‘must’ be implemented. The specification document simply lacks a clear guidance as to how to implement OAuth2 properly. The implementation will depend on the specific scenario you’re working on: the type of the device, type of auth server, absence/presence of a dedicated auth server, communication types etc. So in practice you will have a number of different implementations of the OAuth2 Framework where each implementation can be regarded as an OAuth2 protocol specific to a certain environment.

Bearer tokens

You’ve seen the token type ‘bearer’ in a number of posts of this series. Why is it called ‘bearer’ anyway? It denotes any party who is in possession of the token, i.e. it is the bearer of the token. Anyone who holds the token can use it the same way as any other party also in possession of the token can. It is not required that a bearer produce any – cryptographic – proof that it is the legitimate holder of the token. We saw in this post how this “feature” can be used to hijack a token and impersonate you in another, unsuspecting application.

If you’ve gone through the series on Claims and SAML tokens then you’ll recall that a SAML token must have a signature to verify its authenticity. Therefore a stolen SAML token cannot be used to make other requests on your behalf.

The lack of signatures in bearer tokens means that the only way to protect the token is to use SSL. Programming against SSL might not be the favourite way to spend time for software developers as SSL is riddled with certificate and other validation errors. So they may look for ways to simply ignore SSL errors. This can lead to some half-implemented SSL where the validation errors are ignored: a man-in-the-middle can reroute your HTTP request and attach a false certificate.

Also, SSL may not be implemented in the entire communication chain. It can be decrypted to perform caching and optimisation at the backend server where someone within the receiving company’s intranet can access your token, password, name, email etc.

A more secure version of OAuth2 tokens are MAC tokens. You can read about them here:

Security

The consent screens of companies like Facebook, Google or Twitter can give the everyday user a false sense of security. They are all well-established and generally trusted companies so a web view with the Google logo must be extra safe and reliable, right? An unknown third party application can easily become a trusted app if the user sees that it’s possible to log in with Twitter and Facebook. However, there’s nothing stopping the developer of the app to create a consent screen identical to that of the well-known auth providers. This technique is often used in spoofing attacks to steal your bank account credentials: instead of http://www.mytrustedbank.com/login.aspx you’re directed to http://www.mytrustedbank1.com/login.aspx and the reader may never see the ‘1’ in the URL or give it any importance. The same technique can be used to spoof the consent screens.

However, there’s still a good point in having those consent screens. The developer doesn’t need to worry about storing passwords and usernames securely and the client can still click ‘refuse’ if something looks fishy.

Let’s look at something different: issues with the authorisation endpoint URL.

Recall the following sections in the GET request to the authorisation endpoint of the auth server:

redirect_uri=http://www.mysite/callback&scope=resource&response_type=code

As these sections are part of the URI an attacker can catch your request and start manipulating the string. The redirect_uri can be modified to let the auth server send the token to someone else’s server and get hold of a token meant for you. The scope parameter can be modified to grant access to resources – even extended resources – to the attacker. The response type can also be changed from ‘code’ to ‘token’ to get hold of the token immediately.

This is a point to take care of if you’re planning to build your own OAuth2 authorisation endpoint. You must make sure that the incoming request is validated thoroughly. One way to mitigate the risks is that when the client signs up with your auth server then you register the list of valid redirect URI:s as well and try to limit that list to just one URI. The token then cannot be sent to any arbitrary callback address. The same is true for the other elements in the query string: register all valid scopes and resources for all new clients.

If you manage to hold the range of possible values in the query string to 1 per client then your auth server can even ignore the incoming values in the URI and instead use the registered ones in the database.

Among the resources below you’ll find a couple of very specific examples on how the Facebook OAuth2 implementation was successfully hacked.

Resources

Here’s a couple of articles from Eran Hammmer criticising OAuth2. You may or may not agree with him but you can assume that he is extremely knowledgeable on this topic. Read through the articles and make sure you understand his arguments:

Here are a couple of documents around OAuth2 that were not included in the Framework document mentioned above. If you wish to do any serious work in OAuth2 then you should be familiar with these as well:

There’s a web page which lists a whole range of specs around OAuth2, like JWT tokens, authorisation grants, dynamic client registration, and a whole range of things that could easily fill this blog with posts for the rest of the year: Web Authorization Protocol (oauth)

An excellent overview: How to Think About OAuth

Regarding security around OAuth2 and the possibilities for attacks you can consult the following pages:

Read the next part in this series here.

You can view the list of posts on Security and Cryptography here.

Introduction to OAuth2 part 7: OpenID Connect basics

Introduction

OpenID is a specification that is built on OAuth2. OpenID reuses ideas from the OAuth2 specs like the query strings and token formats, but it specialises in authentication. There are a couple of issues with OAuth2 authentication that OpenID Connect aims to resolve.

OAuth2 authentication issues

According to the specifications OAuth2 is meant for authorisation and not authentication. If you followed along the posts in this series then you know how OAuth2 works, how the client gets a token with limited rights from an auth server, so it’s an example of delegated authorisation using the consent screens. The 3rd party application will then have access to a limited set of features: read but not write tweets on Twitter, view but not add contacts on Facebook etc. Authentication is only the first part of the picture when you fill in your username and password on the consent screen. The auth server then hands out the limited set of rights which forms the authorisation part of the chain.

However, there are cases where the application doesn’t need those rights at all. Instead all it needs is to have an authenticated user. Think of the following scenarios:

  • The app doesn’t have any dedicated user store with the username and password safely tucked away – it is convenient to rely on a trusted service to provide authentication
  • The app needs to know who the user is to make adjustments to the UI – if you log on with Twitter then show Twitter-related links etc.
  • The app needs to limit access to certain features depending on the auth provider, where the features are not directly linked to the type of provider – e.g. give free access to a photo viewer for Twitter users but make it a paid feature for Facebook users, i.e. the photo-viewing feature is unrelated to Twitter or Facebook

If you see the well known “Sign in with Facebook/Twitter/Google/etc” where the application itself has nothing to do with those providers then it can be a sign that those applications use OAuth2 in a way that goes against the specifications.

Another example is using Azure Mobile Services where you can limit the CRUD operations in your backend SQL tables to authorised users. The mobile app can use the most common auth providers to authenticate the user and get hold of an auth ticket, it is built into the Azure SDK. The application however may or may not use the limited features provided by the token and what the user has given his/her consent to.

If you recall from the previous parts then the client may contact the auth server with a URL similar to this in the implicit flow:

GET /authorize?client_id=mymobileapp&redirect_uri=http://www.myapp.com&scope=signin&response_type=token&state=123

The application wants to authenticate the user and thus contacts the auth server with some special scope. The scope is called “signin” which can be an agreed-upon value so that the auth server knows that this is only about authentication and not authorisation. The application is asking for a User Info Endpoint which holds the user’s name, email address etc. If the app manages to get hold of this endpoint then it can safely assume that the user is authenticated and the auth server replies with an access token.

Consider the following problem: you have a malicious app which requires you to sign in with one of the well known auth providers. People usually trust those buttons that say “Log in with Facebook/Twitter/etc” and they happily provide their username and password in the consent screen. The malicious application will receive an auth token to your User Info Endpoint. The app now has access to a token – in fact it steals the token – that can be used to impersonate you in another – legitimate – application. The malicious app swaps some access token in the legitimate application with your token. Your token has been used to impersonate you in another application that you might not even know of. The legitimate application only sees a trusted User Info Endpoint token from a trusted auth provider and it has no way to determine whether it was the user who has just typed in their credentials in a consent screen.

Resources

You’ll find more detailed accounts on the problems with OAuth2 authentication under the following links:

OpenID connect

As stated above OpenID Connect is built on top of OAuth2 and aims to rectify its shortcomings regarding authentication. When the biggest auth providers saw the issues with OAuth2 being used as a purely authentication platform then they started to add specific steps to recheck the User Info Endpoint token. This led to compatibility issues between them as these actions were not co-ordinated. OpenID Connect brings these provider-specific platforms to the same level so that the developers don’t need to tweak their code depending on the auth provider.

OpenID uses two code flows that we saw before: Authorization code flow and Implicit flow. There’s a new token type though called the ID Token. Actually, the concept of User Info Endpoint arose when the OpenID Connect specs were formalised. The specs also add other things that are not found at all in the OAuth2 framework, such as session management, i.e. how to log out users.

Authorization code flow with OpenID connect

The following actors are the same as we saw before in OAuth2:

  • The client app, i.e. the user agent
  • The identity provider, such as Twitter or Google
  • The auth server with the auth endpoint
  • The token endpoint which provides the auth token
  • The identity provider: Google, Twitter, Facebook etc.

The client first sends a GET request to the auth endpoint. The request may take the following form:

/authorize?client_id=mymobileapp&redirect_uri=https://mymobileapp/cb&scope=openid%20profile&response_type=code&state=123

This is basically the same as before – keep in mind that most of the OAuth2 specs are reused in OpenID. The major “invention” here is that OpenID related requests must be identified in the scope parameter where its value will start with “openid”. After the “openid” string you can attach other specifiers such as “profile”, “email” etc. to further specify what claims the application needs. “Profile” provides what it implies: first and last name, email address and the like. The following values are applicable along with the claims they provide:

  • profile: name, family name, given name, middle name, nickname, preferred username, picture, website, gender, birthdate, timezone info, locale, the date when the profile was updated
  • email: email and verified email
  • address: address
  • phone: phone number and verified phone number
  • offline_access: this is a request for a refresh token

The next step is the consent screen provided by the appropriate Identity provider. The user types in their username and password as usual. The consent screen may be specific for the purposes of authentication. Instead of saying “this app will have access to your tweets” it may state that “this app will have access to your Twitter profile” which is an even more limited set of rights compared to the pure OAuth2 variant. If you click “yes” then the auth code is sent back to the client:

GET /the_callback_url?code=abc&state=123

The code is used to retrieve the token from the token endpoint using a POST request:

POST /token

…with the auth header Authorization: Basic client_id:client_pw and also sends the following parameters:

grant_type=authorization_code&authorization_code=abc&redirect_uri=https://mymobileapp/cb

The token endpoint responds with a JSON similar to this one:

{
"access_token" : "abc"
, "id_token": "xyz"
, "expires_in": "3600"
, "token_type": "Bearer"
, "refresh_token" : "mno"
}

…which is very similar to the token we saw in the OAuth2 flow. The new element is the ID token which was missing from the OAuth2 token. The ID token contains a set of JWT formatted claims about the authentication event:

  • Issuer (‘iss’): where the token has originated from, i.e. if it comes from the same ID provider the user has just consulted
  • Subject (‘sub’): identifies the user
  • Audience (‘aud’): identifies which client the token is for. It must be the same client that initiated the request. The client can use this claim to verify if the token was meant for itself. This feature was missing from the OAuth2 type of log in
  • Expiration (‘exp’): how long the token is valid

The ID token is signed and it must be validated by the client. Upon validation success the application will know that the response from the token endpoint was meant for it.

This is the value added by OpenID on top of OAuth2 to provide authentication. We no longer accept just any token and assume that authentication must have succeeded. With the ID token we can validate the token on the client side. The above scenario with the impersonation cannot happen as the legitimate app can validate the incoming token.

If the username is all the application needs to know to function then we’re basically done. The username is available in the subject claim. Otherwise yet another GET request is made from the client to the User Info Endpoint:

GET /userinfo

…with the auth header Authorization: Bearer access_token

The access token is used to retrieve more info about the user from the User Info Endpoint. The User Info Endpoint sends back the claims in JSON format similar to this one:

{
"sub" : "56346552345"
, "name": "John Smith"
, "email": "john@smith.com"
}

You can view the list of posts on Security and Cryptography here.

Introduction to OAuth2 part 5: the resource owner and client flow

Introduction

The previous two posts introduced the code and implicit flows in OAuth2. We’ll now look at the two remaining flows of the OAuth specifications:

  • Resource owner flow
  • Client flow

Resource owner credentials flow

This particular flow is mostly suited for trusted applications. The scenario is similar to what we saw before. A client software installed on a device needs access to a protected resource. We saw earlier how the user had to give consent to the application to collect some limited amount resources before the application could go on with its job.

In this flow this step is missing. It is the client application itself that collects the credentials from the user. Here the application is trusted so the user can enter the username and password without having to go through the consent screen step, where the consent screen comes from the login GUI of the auth server. The user must be able to trust the application and the manufacturer of the application to enter his or her username and password.

A good example is the Twitter app whose login page looks as follows on an iPhone:

Twitter login iOs

There must be sufficient trust towards an application like that. Twitter has a good brand name and good marketing so it’s reasonable to trust an official application that they have endorsed. You can expect that your Twitter credentials won’t be misused otherwise that trust will be broken.

The client app then sends a POST request directly to the auth server. The URI requesting the auth token may look similar to the following:

/token?grant_type=password&scope=the_protected_resource&user_name=username&password=password

The request header will also include a basic auth header with the credentials in order to authenticate with the auth server:

Authorization: Basic clientId:clientPassword

Upon successful authorisation the application receives the usual auth token we saw before, e.g.:

{
"access_token": "somecode",
"expires_in": "expiry time in seconds",
"token_type": "Bearer",
"refresh_token": "somecode"
}

A good practice is that a trusted application collects the password the very first time it is used and it is then forgotten after collecting the auth token from the auth server. The access and refresh tokens are saved on the device but not the password.

The application can then access the protected resource with the auth token:

GET /resourceUri

…with the following header:

Authorization: Bearer access_token

The token can be refreshed with the refresh token once it has expired.

Client credentials flow

This flow is most applicable in machine-to-machine or service-to-service communication. The client sends a POST request to the token endpoint of the auth server:

/token?grant_type=client_credentials&;scope=protected_resource

A Basic auth header will be inserted into the request:

Authorization: Basic (clientId:clientSecret)

The client authenticates itself without involving the resource owner in the flow. The resulting token won’t be associated with any particular user. The client won’t carry out actions on behalf of the user but in its own right.

Read the next part in this series here.

You can view the list of posts on Security and Cryptography here.

Introduction to OAuth2 part 4: the implicit flow

Introduction

We looked at the code flow of OAuth2 in the previous part of this series. We’ll continue by looking at the so-called implicit flow.

The implicit flow is mostly used for clients that run locally on a device, such as an app written for iOS or Windows 8. It is also applicable for packaged software that runs within a user agent on a client device. These act like local clients but they are not written as true native software.

We have to solve the same problem as before: the local application wants to access a protected resource on behalf of the resource owner who is not willing to provide the password. There are a lot of applications that use your data from Twitter, Facebook, LinkedIn, blog platforms etc. The majority of them do not originate from the respective companies but were written by third-party app developers. You as a Facebook user may not be happy to provide your password to those apps due to security concerns.

The solution is similar to what we saw in the case of the code flow: you won’t give your password to the native application but to the auth server. The client app will then retrieve an access token from the auth server which it can use to access the resource.

You’ll see that the implicit flow is really nothing else but a simplified version of the code flow.

Details

First the app will need to contact the auth server of the service the client app is using as the authentication platform. You’ve probably seen options like “sign in with your facebook/google/twitter/etc. account” in some application on iPhone/Android/WindowsPhone. The application must be able to show the login page of the service. The GET request sent to the auth server looks very much like the one we saw previously:

GET /authorize?client_id=mygreatwindows8app&scope=resource&redirect_uri=http://www.mysite.com/redirect&response_type=token&state=some_id

The only difference is response_type=token, the other elements should look familiar. The native application won’t get an access code from the auth server but the token directly. Remember that in the code flow the requesting page had to do some background task where it asked for the token using the code it got from the auth server. This extra step is missing here in the implicit flow.

The native app must be prepared for showing the login page of the auth server. Example: Azure Mobile Services allows a mobile app to register with Microsoft, Facebook, Google and Twitter. So if you write an application and want to let Azure handle the backend service and notifications for you then you can register your app with those services and you can offer your users to log in with the account they wish. The following is the top part of the Azure sign-up page – the full page is too long, but you get the idea:

OAuth signup page on Azure Mobile Services

The application will then need to show the correct login page and consent screen of the selected provider. Here’s an example for the Google login on iOS:

Google login on iOS

This login page can be either shown in a popup window or as an embedded screen within the app, that’s only an implementation detail.

If you give your consent to share your data with the app then the auth server will respond with a GET request to the callback. The request will contain the token details as query parameters in the URL. Example:

GET /redirect#access_token=some_code&expires_in=300&state=same_as_in_the_original_request

Note the ‘#’, it’s not a typo. We won’t use a callback ‘?’ but a callback hash in this case. The callback is hash fragment encoded. The idea with this is that the query parameters won’t be sent to any server, they will be hidden and won’t show up in the referrer URL. Everything after the hash is only meant for the immediate recipient, it won’t be propagated further on. Otherwise the token could leak to a third party.

The token is anyhow exposed to the native app and the browser where the login page is shown. The client app won’t authenticate with the auth server, unlike in the code flow, so usually refresh tokens are not an option. If the client app had to authenticate with the auth server then the client credentials would need to be stored on the device, which is not ideal from a security point of view. Keep in mind that the user won’t have full control over the application, so saving the full credentials locally is normally not a good idea.

The application can now request the protected resource using the token. Usually the token is put into the auth header of the request to the resource server as type ‘Bearer’:

Authorization: Bearer ‘the access token’

We said that refresh tokens are normally not provided in the standard way of implementing the flow. However, this doesn’t mean that there are no workarounds out there. E.g. Google uses a hidden iframe with a cookie to avoid showing the consent screen again and again. The lifetime of the cookie will then be longer than that of the token and the user will have to log in again after 2-3 weeks.

Read the next part in this series here.

You can view the list of posts on Security and Cryptography here.

Introduction to OAuth2 part 3: the code flow

Introduction

Flows are a very important concept in the OAuth2 security chain. Flows describe the way how a client can get hold of the identification token in order to access a protected resource.

There are four different flows according to the OAuth2 specification:

  • Code flow
  • Implicit flow
  • Resource owner flow
  • Client flow

Let’s look at the code flow first in a bit more detail. The posts that follow will discuss the other flows in the list.

Authorisation Code Flow

This flow is most often used for web application clients. The web application wants to access a resource owned by the resource owner. The owner doesn’t want to give a full-access password to the application. Instead they will rely on an OAuth2 service to retrieve a limited-access token.

The web application will first ask an authorisation server for the token via a GET request. A typical URI to get that token may look like this:

GET /auth?client_id=greatapp_id&scope=protected_resource&redirect_uri=http://greatapp/callback&response_type=code&state=123

the URI consists of the following elements:

  • client_id: the name of the client that’s trying to access the resource. The client needs to be registered with the auth server. So before anything can happen the client needs to go through this registration step.
  • scope: the name of the resource the client is trying to access
  • redirect_uri: the URI to redirect to upon retrieving the resource. This is a callback URI through which the auth server will send back a so-called authorisation code
  • state: an optional random number that the client provides. It can be stored locally and can be used as a correlation ID. The auth server will send back the state parameter in its response so that the client can match it up with what it has saved locally. This is a good protection against Cross Site Request Forgery

So the GET request arrives at the auth server. The client will need to authenticate itself. That’s when you see these login screens that are becoming ubiquitous in the world of Facebook, Twitter, Google etc. identification scenarios, e.g.:

Google OAuth screen

Without this step the auth server will not be able to make any security decisions.

The full GET request by Google in this example looks like this:

https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=108380595987-4e427srhd9jr0lsnohleutb2ilbuof70.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fpublic-api.wordpress.com%2Fconnect%2F%3Fmagic%3Dkeyring%26service%3Dgoogle_plus%26action%3Dverify&state=8183180&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.stream.write+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.login&access_type=offline&approval_prompt=force&request_visible_actions=http%3A%2F%2Fschemas.google.com%2FCreateActivity

…which has the following – by now familiar – sections:

  • response_type=code
  • client_id=108380595987-4e427srhd9jr0lsnohleutb2ilbuof70.apps.googleusercontent.com
  • scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.stream.write+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.login
  • redirect_uri=https%3A%2F%2Fpublic-api.wordpress.com%2Fconnect%2F%3Fmagic%3Dkeyring%26service%3Dgoogle_plus%26action%3Dverify&state=8183180&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.stream.write+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.login&access_type=offline
  • state=8183180

…and some other sections as well, but these are the most important ones I believe.

Next, the client will have to give its consent on the so-called consent screen:

Google consent screen

So you see that it is WordPress that’s making the request. An informative consent screen will also tell you which resources the requesting application wants to gain access to. This screen is a question to the user: do you agree that the WordPress client gains access to some specific Google+ resources about you? Then you can say yes or no.

If you say yes then Google auth server will give WordPress an auth token with just enough claims to access the requested resources.

Here’s another example by Twitter:

Twitter OAuth screen

The point is that the requesting client – WordPress – will get some limited amount of access to resources owned by someone else without giving out the password which would give them full access.

The consent screen is a very important step. If you’re planning to build a custom OAuth server then make sure to make this screen as informative as possible. An extra option is setting a time limit to access rights.

If you click OK then the auth server will redirect you to the callback URI and present the authorisation code to the requesting application. The auth code is not yet the access token. The token is requested in the next step.

Now that the client application has the auth code it will directly ask the auth server for the token. The communication takes the form of a POST request that includes the following parameters:

grant_type=authorization_code&authorization_code=same_code_that_was_provided_in_the_first_response_from_auth_server&redirect_uri=must_be_same_as_before_so_that_auth_server_can_verify_validity

The client will have to authenticate with the auth server using the credentials it received during the initial registration process mentioned above. The client will send the auth code to the auth server. The auth server will verify its validity and that the code belongs to the original requesting application. If the auth server is happy then it sends back a JSON formatted token. In a reduced form it can look like the following:

{
"access_token" : "some name"
, "expires_in": "number of seconds"
, "token_type": "Bearer"
}

An access_token coupled with the expires_in parameter is a token with a time limit on its validity. The client will get access to the resource with this access token. We’ll discuss bearer tokens in a later post.

As you see the access token has a limit on its validity as defined by the expires_in parameter. If it’s set to 10 minutes then the client loses its access to the protected resource after 10 minutes. The user will then need to go through the consent process. The client will also need to ask for a new token. That’s certainly an option but it’s not very efficient. Imagine having to give consent to show your tweets on a page, such as here on WordPress, every 10 minutes otherwise the service stops.

Instead the JSON token can be extended with a refresh_token parameter:

{
"access_token" : "some name"
, "expires_in": "number of seconds"
, "token_type": "Bearer"
, "refresh_token": "some name"
}

With this extended token the application will be able to request new tokens without the user giving consent every time. It sends a POST request to the auth server with the following parameters:

grant_type=refresh_token&refresh_token=(same name as the refresh_token parameter in the JSON above)

The token will also contain a range of other things, such as claims and a signature. Please refer to this post for an introduction on JSON Web Tokens. Keep in mind that it’s up to you as the application developer to decide which claims need to be included in the full access token.

From this point on with refresh tokens the application will have access to the resource for ever which is not always desired. Normally an application will let you remove your consent, such as the following screen in WordPress:

WordPress client management

Read the next part in this series here.

You can view the list of posts on Security and Cryptography here.

Introduction to OAuth2 part 2: foundations

Introduction

OAuth and OAuth2 has become an important term in web and mobile security. According to the OAuth homepage it’s “an open protocol that allows secure authorisation in a simple and standard method from web, mobile and desktop applications.” About OAuth2 is says specifically that it is an “authorisation framework that enables a third-party application to obtain limited access to a HTTP service.”

In this post we’ll look at the foundations of OAuth2: some theory and background and the most important terminology. We’ll continue the series with the different auth flows in OAuth2 in the following posts.

OAuth2 basics

The starting point is simple: you as a user would like to retrieve some data from an online resource. You may do so from a web browser, a mobile phone, a tablet or some other similar device with internet connection. In traditional enterprise software all elements of an authorisation system belonged to the same organisation: the client software, the backend resources, the separate authorisation server if any. If a user wanted to access your resources then they navigated to your homepage, logged on and performed what they were allowed to do depending on their access rights.

In the world of the web services, mobile devices and mobile applications we need to separate the parts a little. According to the OAuth specification there’s a distinction between a “client” and a “resource owner”. The distinction becomes important as nowadays we can have a multitude of applications consuming a resource that belongs to someone else. Building web services that expose some type of data is a huge thing in the world of software development. It is one of the drivers behind the popularity of Twitter, Facebook etc. Would you like to write your own little Facebook app? Here are the public endpoints with the SDKs, happy coding! In this case it’s not unthinkable that the owner of the software is not the same – i.e. does not belong to the same trusted subsystem – as the owner of the resource that the software is using. In OAuth therefore the client is the software itself that accesses a certain resource. The resource owner will still be part of the trusted system but naturally such third-party tools may fall outside. Just because you write a Twitter-app your software will not become a trusted application.

A frequent analogy used to describe OAuth2 is Valet parking which is quite common in the US. You give the key of your car to a person who will park it for you. You are the resource owner, the car is the resource, the key is the password and the person who parks your car – the valet – is the third party system which is more or less trusted. You shouldn’t of course provide your password to anyone like that thinking that the person won’t do anything harmful. The most expensive cars often have two sets of keys – a “normal” key and a valet-parking key. The valet-parking key provides limited access to the car: you can drive it for a couple of miles, you cannot open the boot (trunk) etc. The target in OAuth2 is similar in the digital world: you as the resource owner have 2 sets of keys. You have the password which gives full access to a resource and another one which gives limited rights in a digital transaction.

There are 4 important components in the OAuth setup:

  • Client: as mentioned above, this is the software accessing a protected resource. The client may be private or public and trusted or untrusted
  • Resource owner: the person/organisation who owns the resource the software is trying to access
  • Resource server: the machine where the resource is stored
  • Authorisation server: the server that can issue the limited access keys

By default the resource server and the authorisation server must belong to the same trust system. The auth server knows about the protected resources and the resource server knows how to read the limited access key issued by the auth server.

In enterprise software the trusted software would very likely be part of the same trusted system. Nowadays we can have partially – or not at all – trusted clients built by millions of mobile app developers in the world. The organisation who owns the resource will probably not have any control over the quality of those third-party applications.

The client will need some sort of a limited access key to access the protected resource. This is the purpose of the authorisation server which can issue such tokens to registered clients. Using that key the client will be able to access the resource. This is very similar to the process of single sign-on we saw here where an external authorisation server provides a SAML token with some initial amount of claims to registered users. The SAML token can be then used to access the protected service. The main difference is that in the enterprise-like WS-Trust specification with the SAML tokens the client is implicitly trusted.

Flows

OAuth2 must work with a wide range of consuming applications so no wonder that there are various ways to get hold of the limited access token.

OAuth2 defines a number of different flows as to how to access a protected resource. We’ll look at these in more detail later, this is just to give some idea on what’s coming up:

  1. Authorisation code flow: used in conjunction with web application clients
  2. Implicit flow: used with native – user-agent based – clients
  3. Resource owner password credential flow: is used with trusted clients
  4. Client credential flow: used in client-to-service communication

Useful resources

We’ll see very little code in this series. I’ll instead concentrate on giving an introduction to this relatively new field of security. Also, unlike with claims, there’s no native C# library with objects around OAuth2 and OpenID in .NET at the time of writing these posts. By “native” I mean something that is e.g. part of the System.Security namespace. So writing these classes on my own in my free time can be a challenge.

However, you don’t need to start from scratch. Like we saw in the series on claims, Thinktecture has prepared a lot of work in this area as well. You can install their library from NuGet and use it on your .NET project:

Thinktecture library in NuGet

You can read about this project with examples on its GitHub repository.

We briefly looked at the ThinkTecture identity server in the claims series. You can find its GitHub page here. Check out its Wiki page for extensive demos and how-tos.

We’ll continue the series on a discussion of the different auth flows. Read the next instalment here.

You can view the list of posts on Security and Cryptography here.

Introduction to OAuth2: Json Web Tokens

Introduction

JSON web tokens are a sort of security token. As such, it is used for authentication purposes, and has similar attributes like the XLM-formatted SAML tokens we met in the series on Claims Bases Authentication. It shows the issuer of the token, the claims about the user, it must be signed to make it tamper-proof and it can have an expiration date. If you then log on to a web page then the authentication server will send back a security token that contains the data mentioned above. Upon successful authentication the web site will consume the token.

Again, like in the case of the SAML tokens there must be a trust relationship between the consumer and the issuer of the token. This ensures that even the contents of the token are trusted. The consumer knows about the key that the issuer uses to sign the token. That key can be used for validation purposes. At the time of writing this post SAML tokens are the most commonly used security tokens. SAML has quite a complex structure with a strict schema involved. It is very expressive with various encryption and signature options.

This last point is actually a limitation in the world of mobile devices. It’s needless to say how widespread mobile devices are in the world. There are probably more tablets and smartphones available nowadays than laptops and stationary computers. It feels like it’s only programmers like me who need computers… Mobile devices must perform their tasks with resources that are limited in comparison to computers. They are not well suited for parsing complex XML tokens.

This is where the JSON web tokens enter the scene with their simplified structure. The data is JSON which is more compact than XML and even mobile devices have the ability to parse them. JSON is also native to JavaScript which has grown into a very important language with applications such as Node.js, Windows 8 store apps, MongoDb etc. There are still a number of symmetric and asymmetric encryption options available for the token content and signature but it’s limited compared to what the SAML standard has to offer. However, the most widely accepted algorithms, such as RSA and AES are available and they will suit the vast majority of needs.

With the fast advance of mobile devices JSON web tokens will soon become – or already have? – the new standard for security tokens. They are already the de facto standard for OAuth2 and OpenID Connect in the modern mobile implementations.

Structure

A JSON security token consists of two parts:

  • Header with some metadata, e.g. on the algorithms and keys used to encrypt and sign the message
  • Claims

If you don’t know what claims are then make sure you understand the basics: start here.

These claims can be token specific, such as Issuer, Expiration date, or they can be defined by the application. You as the programmer are free to define what goes into the application-specific claims, such as FirstName, Email, NameOfPet, FavouriteColour, you name it.

If you’ve read through the series on Claims Based Auth available on this blog then the token specific claims are probably familiar to you:

  • Issuer: the identifier of the issuer of the token so that the recipient knows where the token is coming from
  • Audience: shows who the token is targeted at so that the recipient doesn’t use a token meant for a different application or website
  • IssuedAt: when the token was issued
  • Expiration: the expiration date of the token
  • Subject: typically a user ID that describes who the token is meant for

To keep the token size limited these claim types are abbreviated:

  • Issuer: iss
  • Audience: aud
  • IssuedAt: iat
  • Expiration: exp
  • Subject: sub

This is what a header can look like:

{
"typ": "JWT"
, "alg": "HS256"
}

Type: JWT means of course Json Web Token. Alg shows that the HMACSHA256 algorithm was used to sign the token.

The claims section can look like this:

{
"iss": "issuer name, usually some URL http://www.myauthenticationserver.com",
"exp": "a date in UNIX date format i.e. the number of seconds since 1970/01/01",
"aud": "the URL of the consumer likehttp: //www.mygreatsite.com",
"sub": "user identifier such as bobthebuilder"
}

Other claim types can be useful in the claims section: e.g. “client” to identify the application that requested the token. or “scope” to show the list of allowed operations for authorisation purposes:

{
"scope": ["read", "search"]
}

The list of claims can be extended as you wish, just as we saw in the case of SAML claims based authentication.

To make the token even more compact, the different sections are base64 encoded:

sdfgsdfgdfg.hrtg34twefwf4fg5g45gg.wsefefg345e4gf5g

These are just random characters, but locate the 2 periods in this string. They are delimiters for:

  1. Header
  2. Claims
  3. Signature

…where each section is individually base64 encoded.

Some code

Open Visual Studio 2012 or higher, create a console application and add the below package from NuGet:

JWT package from NuGet

In addition, add a reference to the System.IdentityModel library.

There’s a number of ways to exchange JWT tokens between a sender and a receiver. In the below example I’ll use an RSACryptoServiceProvider to sign the JWT so that the receiver can validate it. If you don’t what RSA and asymmetric encryption mean then make sure to read upon it in the blog post mentioned above.

In short: the sender, i.e. the issuer of the token will have a pair of asymmetric encryption keys. The public key can be distributed to the receivers. The receiver will use the public key to validate the signature of the JWT token.

We won’t build a separate sender and receiver, that’s not the point here, but we want to simulate that the sender has access to both the private and public keys and the receiver only has the public key.

The following method will construct a valid RSA key pair:

private static RsaKeyGenerationResult GenerateRsaKeys()
{
	RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider(2048);
	RSAParameters publicKey = myRSA.ExportParameters(true);
	RsaKeyGenerationResult result = new RsaKeyGenerationResult();
	result.PublicAndPrivateKey = myRSA.ToXmlString(true);
	result.PublicKeyOnly = myRSA.ToXmlString(false);
	return result;
}

…where RsaKeyGenerationResult is a DTO:

public class RsaKeyGenerationResult
{
	public string PublicKeyOnly { get; set; }
	public string PublicAndPrivateKey { get; set; }
}

In GenerateRsaKeys() we generate an RSA key and save its full set of keys and the public key only in two separate parameters of the RsaKeyGenerationResult object.

This is how to build and serialise the token:

RSACryptoServiceProvider publicAndPrivate = new RSACryptoServiceProvider();			
RsaKeyGenerationResult keyGenerationResult = GenerateRsaKeys();

publicAndPrivate.FromXmlString(keyGenerationResult.PublicAndPrivateKey);
JwtSecurityToken jwtToken = new JwtSecurityToken
	(issuer: "http://issuer.com", audience: "http://mysite.com"
	, claims: new List<Claim>() { new Claim(ClaimTypes.Name, "Andras Nemes") }
	, lifetime: new Lifetime(DateTime.UtcNow, DateTime.UtcNow.AddHours(1))
	, signingCredentials: new SigningCredentials(new RsaSecurityKey(publicAndPrivate)
		, SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest));

JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
string tokenString = tokenHandler.WriteToken(jwtToken);

Console.WriteLine("Token string: {0}", tokenString);

You’ll recognise the parameters in the JwtSecurityToken constructor. You’ll see that we used the full RSA key to sign the token. The SecurityAlgorithms string enumeration stores the fully qualified names of the signature and digest algorithm. Those are compulsory arguments in the constructor.

Run the code up to this point and you should see a long string with the 3 segments mentioned above.

If your organisation has a valid X509 certificate then it can be used in place of the RsaSecurityKey object. Check out the X509AsymmetricSecurityKey object which accepts a 509Certificate2 object in its constructor. You’ll need to export the certificate with both the private and public keys and save it as a .pfx file. You can do that using the certmgr snap-in in Windows. Use the full file name of the .pfx file in the constructor of the X509Certificate2 constructor.

You can transmit the token in a number of different ways: in the header of an HTTP request, in the query string, in a cookie, etc. It’s now a string that you can send to the consumer.

The consumer can validate and read the claims from the token as follows:

JwtSecurityToken tokenReceived = new JwtSecurityToken(tokenString);

RSACryptoServiceProvider publicOnly = new RSACryptoServiceProvider();
publicOnly.FromXmlString(keyGenerationResult.PublicKeyOnly);
TokenValidationParameters validationParameters = new TokenValidationParameters()			
{
	ValidIssuer = "http://issuer.com"
	,AllowedAudience = "http://mysite.com"
	, SigningToken = new RsaSecurityToken(publicOnly)
};
			
JwtSecurityTokenHandler recipientTokenHandler = new JwtSecurityTokenHandler();
ClaimsPrincipal claimsPrincipal = recipientTokenHandler.ValidateToken(tokenReceived, validationParameters);

The client receives the base64 string which can be used in the constructor of the JwtSecurityToken object. We then use the public-key-only version of the RSACryptoServiceProvider to simulate that the receiver only has access to the public key of the sender. The TokenValidationParameters object can be used to build the validation logic. The JwtSecurityTokenHandler object is then used to validate the token. Upon successful validation you’ll get the ClaimsPrincipal which you’ll recognise from the posts on claims based auth mentioned above.

Set a breakpoint after the last line of code and inspect the contents of the claimsPrincipal object by hovering over it in VS.

The encoded JWT token can be decoded on this web page:

Jwt decoder page

Read the next part in this series here.

You can view the list of posts on Security and Cryptography here.

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: