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?
- A user access our front end
- If the user is not authenticated, (s)he will be redirected to Azure Active Directory (AAD) to login
- AAD will redirect (on success) with an authorization token
- We’ll inject this authorization token into the calls made to the backend (to prove your identity)
- 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!
Understanding JWT Tokens
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
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.
- 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.