Single Page Webapp : How to secure your app and your API with Azure Active Directory

Introduction

A few months ago I did a post on using PHP to connect to the Azure management API. And a week ago I did a demo on how to secure a “classic” webapp with Azure Active Directory. Today we’ll look how to secure a single page webapp by using Azure Active Directory. For the post of today I’ll be using two webapps ;

  • Front end ; a small webapp based using AngularJS
  • Backend ; also a small webapp based on PHP, which will serve the API calls made from the front end

Why does this kind of setup differ from a “classic” approach? With single page apps, we see a very clear segregation of  backend & front end. When the backend & front end are combined, we often see more simple mechanisms used, often based on session information. When the two are clearly separated, we’ll need to authenticate to both individually… I’ve often seen the error where organizations just protect the front end, as this is where the user logs in. And they forget to secure the backend API… An unsecure API means that everyone who can access that API will be able to retrieve (or delete/adjust) the data served by that API. Let that one sink in!

 

Flow of the day

So what will we be doing today?

  1. A user access our front end
  2. If the user is not authenticated, (s)he will be redirected to Azure Active Directory (AAD) to login
  3. AAD will redirect (on success) with an authorization token
  4. We’ll inject this authorization token into the calls made to the backend (to prove your identity)
  5. The backend API will validate the authorization token and verify it against the issuer (AAD)

 

 

Technology Used : ADAL

If you haven’t heard of “ADAL” (Azure Active Directory Authentication Libraries), check them out! A feedback I got from Thomas after that post was ; “You really do not want to write your own code for this…”, and he is more than right on that call. Writing such a code is very interesting to learn to flow and you’ll soon notice that you do not want to do this. Just check out the flows as described on the AAD+Oauth at the documentation page. In addition, these libraries are maintained and receive bug bounties to ensure that their security is beyond everyone’s expected level!

That being said, JavaScript (and thus also AngularJS) is a supported language for ADAL. Though, sadly enough, there is no support for PHP. Thank god I only needed to validate the JWT token at the backend, so I resorted to the firebase/php-jwt library for this.

 

Understanding JWT Tokens

Not familiar with JWT tokens? I can’t blame you. Check out Auth0’s JWT.io to get more insights into this method. Or you can always check out RFC7519 yourself too. 😉

We’ll going for a bit of time travel and fast forward into one of the steps we’ll be discussing later on… If we would dissect one of the API calls, you’ll notice that a header (called “Authorization”) was added. This will start with “Bearer” and the “mumbo jumbo” you see after that is called a “JWT” token.

Now I’m going to copy that token, and paste it into “JWT.io” to deserialize it…

Here we can see that there are three parts ;

  • Header : The “metadata” to describe the cryptographic operations applied to the JWT.
  • Payload : Here we have our various “claims”… Basically, the information we want to rely on.
  • Signature : This follows the basic principle that is also used for certificate verification.

 

When looking towards the claims, here we can see who issued it. The claim called “ISS” is the one who issued it, and “aud” (audience) describes who the claim is for. The issuer is the ID of my AAD tenant, and the audience refers to the application id used for the OAuth flow ;

In regards to the signature, this is a typical private/public key flow. When looking towards Azure Active Directory, you can find the public keys here… We’ll be using these later on to validate the authenticity of our JWT token.

 

Demo Code : Front end

Source Repository : kvaes/Azure-SinglePageWebapp-Auth-Example

Language : AngularJS

Libraries : ADAL.js

Demo URL : https://spaauthdemo.kvaes.be

 

So what can we find in there? In the app we’ve made some basic configurations in the adalProvider.init ;

And in terms of the routes, we’ve added “requireADLogin: true” to our /CatList ;

Once we are logged in, we can even see the claims from our tokens by going to the “User” section ;

This reflects the information we saw when we deserialized the token earlier on.

In terms of the API calls, we have a list of our functions… and ADAL.js will add the Authorization token (in JWT format) “magically”. This is what we saw earlier in the screenshot shown in the JWT paragraph.

 

Demo Code : Backend

Source Repository : kvaes/Azure-SinglePageWebapp-Auth-Example-Backend

Language : PHP

Libraries : firebase/php-jwt

Demo URL : https://spaauthdemoapi.kvaes.be

 

In terms of the API, check out the simple PHP source

In summary ;

  • Get the Authorization header
  • Get the public keys from AAD
  • Verify the authenticity of the authorization token
  • Match the audience (aud) claim to our application ID

 

The Results

You can roll this demo yourself… both repositories are available under the MIT license. So basically; have fun & don’t complain about what you got. 🙂 In the end you should see ;

Three legendary cats from our “Cat Manager 2017” app. 😉 Bare in mind that the CRUD functions do not work, so the api is very dumb and just keeps returning the three cats as results.

 

Closing Thoughts

  • OAuth isn’t always easy to comprehend. You really do not want to write your own libraries on that. Leverage existing libraries!
  • Protect your API…  Protect your API… Protect your API… Protect your API!!! Really, protect your API!
  • Protecting your API is not that hard, as you can see above. It requires a bit of effort, but the libraries take a lot of the “rocket science” away from the equation.
Advertisements

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