Accessing a Protected Resource
In this third and final article we’ll have a look at how to access a protected resource using an access token. In part 1 and part 2 we looked at how to authenticate and obtain an access token from an OAuth2/OpenID Connect identity server.
We will now look at how to include that token as part of a request for a protected resource and how the protected resource can check the token. The example projects can be found here:
In the test project there is a test called
TestGet_valid_token_is_used_to_call_my_really_useful_api. This test obtains an access token using the resource owner password credential flow. This flow differs from the implicit flow used in previous articles in that it passes the resource owner’s username and password to the identity server. It’s a flow which should be used with some caution in real world scenarios as it exposes highly privileged credentials to the client. However it would not be practical to have a unit test which displayed the identity server login page. The code uses the
Thinktecture.IdentityModel.Client nuget package which encapsulates the OAuth2 flows making it very easy to request the token. To make the request for the protected resource we use a regular
HttpClient instance but the Thinktecture client library attaches an extension method called
SetBearerToken. This sets the token in the authorization header using the bearer scheme which is the preferred way to transmit the access token in the request (as defined in RFC 6750). We then set the URI for the request and await the async response.
On the api side we’re plugging in the token validation as part of the OWIN pipeline. The
Startup class uses some
IAppBuilder extension methods defined in
Thinktecture.IdentityModel.Owin.ScopeValidation. Essentially this plugs in the logic to look at the incoming token via the token validation endpoint which we used in the .net 2.0 project to decrypt the token so that we could display it on screen (not something we’d want to do in a real application). The claims are then extracted from the decrypted token and passed to a
ClaimsIdentity instance which is then passed as a constructor argument to an
AuthenticationTicket instance which is in turn passed as an argument to a call to
SetTicket on the
What this all means is that the user can now be authorized to use the api according to their claims. In this example we’ve specified that users must have read and write access to be considered authorized. We then just decorate our api methods with an
AuthorizeAttribute and they will only be able to access the method if they have the read and write scopes defined in the access token. For more fine-grained control have a look at the
ResourceActionAuthorizeAttribute and the
ScopeAuthorizeAttribute in the
Assuming you have both the identity server and MyReallyUsefulApi running both tests should pass indicating that access is granted when a valid token is received and that it is denied when that token is not present.
To summarise, in this final article on OAuth2 and OpenID Connect we’ve seen how to include an access token with a request to a protected resource and how to make that resource validate the token and allow access according to the claims within it. I’d recommend becoming familiar with the specs for both OAuth2 and OpenID Connect. Security is a complex domain and ultimately responsibility lies with you for your own applications. I’ve made extensive use of the open source Thinktecture repositories because they are very comprehensive and active projects. This series of articles has documented how I’ve used code from these projects and transplanted it into my own very simple projects. Doing this was very useful for my own understanding of OAuth2 and OpenID Connect. I don’t profess to be an expert in these areas so please don’t consider this to be anything like an out of the box solution. However I do hope that I’ve provided enough information to help others to get started.