More Secure JavaScript Single-Page Applications with MSAL 2.0 and OAuth 2.0 Auth Code Flow with PKCE

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi i'm jason specklin the cloud solution architect at microsoft and this is today's azure dev tip in today's tip we're going to talk about how your javascript single page applications can authenticate to azure active directory now microsoft has just released version 2.0 of msal that's the microsoft authentication library for javascript now version 1 of msal supported oauth 2.0 implicit grant flow whereas version 2.0 doesn't support that it supports the oauth 2.0 auth code flow with pkce what's the difference security but before we get into how to update your applications and don't worry it's actually pretty easy let's dig a little deeper into how these oauth flows actually work i bet you're thinking i'm about to show you a diagram that looks like this but i'm not you see i mean these diagrams are great and all but sometimes i feel an analogy can be a little more instructive so this is my analogy bear with me for a moment okay so in this analogy we have a jewelry store and this jewelry store keeps all of its best jewels inside a safe deposit box here at the bank of oauth now they would like for their employee to be able to go into the safe deposit box and get a blue diamond for their customers now what they could do is just give their username and password to their employee and their employee would go to the safe deposit box and they could get the blue diamond and the red ruby and every other jewel in the place and run off to a country that has no extradition treaty that's not what we want to happen but if you think about it that's actually the way we kind of treated applications for a long time and we just gave our username and password up and hoped for the best but thankfully oauth came around to kind of relieve us of this burden so let us imagine another way that this might work so here the employee has an id separate and distinct from the id and password of the jewelry store so in this case the employee goes to the first teller presents his id and says i am jason and i would like to get the blue diamond the teller then calls the jewelry store the jewelry store provides their username and password and the teller says hey jason is here and wants to get the blue diamond is that okay so the jewelry store will say yes and the teller will print out a ticket and this ticket says jason from the jewelry store can get blue diamonds for one hour the teller will give me the ticket and i will take it to the security guard now the security guard is always a bit suspicious so the security guard is going to call teller number one and say hey did you print this ticket the teller will say yes i did so the security guard will let the employee into the safe deposit box and allow the employee to only take the blue diamond so how does this actually work in the real world what is this analogy all about so in this case the jewelry store represents the user and this employee represents the app which might not be entirely trusted so the app then connects to the authentication endpoint the authentication endpoint redirects the user okay this is kind of where it breaks down a little redirects the user to the login screen ask them to log in if they're not already logged in and then presents them with the permissions that the app is requesting or the scope so in this analogy the scope the app is requesting is the ability to get blue diamonds in the real world the scope would be something like can read your email or can write to files so it will pop up that permission request separately and distinctly from the authentication if the user approves of the scope then the authentication endpoint will produce an access token that access token will be returned to the app the same way the app got there by redirecting back to that application now the way the redirect works this token actually needs to appear in the url fragment of this um of this url so it's going to be redirecting back to the url of the app with the access token uh stuck on after like the hashtag and then the app can grab that access token and will present it to the api as a bearer token the api then should check the validity of that access token and then allow the application to do what is requested in the scope so in our analogy getting blue diamonds in the real world reading emails writing files etc however there is a problem let us imagine instead that a hacker has taken up residence inside of our bank so what happens is the employee goes to the teller says i am jason i would like to access the blue diamond the teller then calls the jewelry store the jewelry store provides their username and password the teller asks hey can jason get blue diamonds the jewelry store says yes the teller prints up a ticket that says jason from the jewelry store can get blue diamonds for one hour gives it to jason but at this point the hacker takes a picture of the ticket that hacker then goes to the security guard shows them the ticket the security guard validates the ticket and it is valid the teller did print it out and so allows the hacker to get in and steal blue diamonds from the safe deposit box so what's the actual real world flaw here well it comes from this token again remember the user agent was redirected to the off endpoint and the off endpoint needs to redirect right back so this access token is going to appear right in the url bar so in this analogy this hacker has to do a fair bit of work in order to get this to happen he has to set up in the bank he has to have a camera he has to not be noticed in the real world the way this kind of hack works is there'd be some cross-site scripting vulnerability so a javascript injection or a rogue npm package or perhaps even just some plain old malware running somewhere else on this user's computer so it takes some doing but it is very possible for this hacker to be able to steal that ticket so what can we do about this how can we mitigate this and prevent the hacker from stealing the blue diamonds well let us imagine in this other case that the employee now not only has a username but also has a password so in this instance the employee goes to the teller and says i am jason i would like the blue diamond does not provide a password the teller then calls the jewelry store jewelry star authenticates with their username and password the teller says jason would like to get the blue diamond the jewelry store says yes and so the teller prints a ticket now this ticket is different this ticket says jason from the jewelry store can get one ticket one token excuse me in the next 10 minutes he then gives him that ticket he takes that to the next teller but he puts them in an envelope hands the envelope to the second teller the teller then verifies the password and then the second teller prints out a ticket that says jason from the jewelry store can get blue diamonds for one hour he then puts that ticket inside an envelope and now jason can get that ticket use it to present to the security guard the security guard will always check with the teller to make sure he printed it and then we'll allow jason into the safe deposit box to get the blue diamond how is the hacker thwarted the hacker is thwarted because by putting it in an envelope the hacker can't take a picture of it and because this response is inside an envelope that hacker can't take a picture of that either so again how does this very stretched fin analogy actually work in the real world well the way it works in the real world is that from the first teller you're getting an off token and this auth token allows you to get one token in the next 10 minutes so again this redirect does have to happen in the url fragments so the hacker can still take a picture of that okay that ticket is still of open and available for a well-situated hacker to get at but what the hacker does not have is the password so the hacker can certainly get his own envelope and can certainly hand it to teller number two which is the token endpoint but that hacker doesn't have the password and so will not get this ticket that allows the app to authenticate to the api using it as a bearer token he puts that in an envelope which is to say the response to the post request that was sent earlier again something a hacker is not going to be able to see easily and then he uses that to authenticate to the api doing the things that the scope allows him to do and this works great except for one problem the problem is this guy cannot keep a secret to save his darn life see this guy is a javascript single page application running in the context of a browser now this flow works great for confidential clients it's called the oauth 2.0 auth code flow but there is no place that this guy can store a secret where this guy can't already just reach in and grab it he could store it in local storage or a cookie or something but this hacker is always going to be able to get that password rendering this whole thing moot which is why the implicit grant flow exists at all how can we get around this issue and still be secure well what we can do is use the newer oauth 2.0 auth code flow with pkce that's proof key for code exchange so in this instance we have the employee once again who has an id but no password so the employee once again goes to the first teller says i am jason and i would like the blue diamond the teller then says okay think of a number between one and a hundred so the employee thinks okay uh 38 why not and then the teller then calls the jewelry store the jewelry store authenticates with the username and password the teller asks can jason get the blue diamond the jewelry store says yes and so the teller prints up a ticket that says jason from the jewelry store can get one token in the next 10 minutes just as before so then the employee takes the ticket as well as the id and the random number that he just thought up and puts it in an envelope and then within the next 10 minutes goes to the second teller the second teller then verifies that the random number that is in the envelope is the same one that he thought of less than 10 minutes ago if that is the case he will print up a ticket that says jason from the jewelry store can get blue diamonds for one hour put it in an envelope then the employee can get it from the envelope go to the security guard present it to him the security guard as always will check the ticket make sure it was printed by teller number two allow the employee to go into the safe deposit box and get the blue diamond so in this case the hacker is thwarted by the random number okay so the hacker can't see the random number that the employee thought of the hacker can't see this number 38 over here as before the hacker can absolutely uh see this jason from the jewelry store can get one token in the next 10 minutes ticket and he's got to operate fast if he's going to get it first but what he doesn't know is that random number that the employee thought up so there's no password to be discovered and the hacker is thwarted so how does this work in the real world well in the real world instead of thinking of a number between 1 and 100 the client needs to create a cryptographically random string and present it to that authentication endpoint then the authentication endpoint will provide it with the token the auth token again because of the way the redirects work must be on that uh fragment of the url so again trivially gettable by that hacker but what the hacker does not have is that cryptographically random code that was presented to the first teller so then the second teller or the token endpoint will verify that this post request contains that very same cryptographically random string and if it does not he will not issue the bearer token that allows the app to get into the api so with that very stretched thin very elaborate analogy out of the way let's see how you can actually modify your msal code to take advantage of this new oauth flow so here i have a simple single page javascript application written in view.js now this application can authenticate using both msal1 or msal2 as the user chooses so here is my msal 1 service and to do that i import star as msal from msal that's the name of the npm package and to create my msal object i do this dot my msal equals new msal dot user agent application and i pass it in my configuration now let's take a look at the msal 2 auth service here i import star as msal from at azure slash msl browser that's the new name of the msal 2.0 package so if you start upgrading just msal you're not going to get 2.0 because they work pretty differently so then we create it by saying this dot my msal equals new msal taught public client application and we pass it in the config and that's essentially it i mean it takes the exact same configuration as msal1 it just uses an entirely different flow behind the scenes other than that everything just works the same it's pretty easy to upgrade so let's see this application at work all this app does is it authenticates using the library of my choice and then it just goes into office graph and gets all the groups that i'm a member of so first let me select msal1 i will log in and i'll give my username and password and then i will select get groups and that is going to actually request the auth token so i'll click on that and uh you can see that it got the groups that i'm a member of so it worked that's always nice and we can see here that here's the url that i got and remember these have to be get requests because it works all through redirects here i have the redirect uri that's encoded in there and all the stuff is encoded right there in that url and you can see what it's going to call me back with it's going to call back this localhost address and here right on that url bar in the fragment is my access token okay i can take this access token as is and present it to the microsoft graph and for as long as this token is valid which should be about an hour it will allow me to get all the groups and so here's me making that call i'm using a get request and i am providing it with that bearer token and that's uh that is the implicit grant flow at work now let's see the exact same thing but this time using msal2 so i'll click msal2 i will log in it's going to once again pop up an authentication window my username and password will be entered okay and let me get my groups and there are my groups so here let's take a look at the token endpoint that we called oh so this is the options call we got to verify we could do cores and here is the post request we made and if we look into this post request we can see first the off code that we got from our initial call when we logged in as well as the code verifier and that is that cryptographically random string that we need to generate and then present to the token endpoint in order to get a bearer token and here you can see we called the member of endpoint and we had a bearer token to call and that shows just how easy it is to make your javascript single page applications just a little more secure by using msal 2.0 this has been today's azure dev tip thank you so much and as always happy coding
Info
Channel: Microsoft DevRadio
Views: 7,965
Rating: 4.9402986 out of 5
Keywords:
Id: YxAwGAnmNqQ
Channel Id: undefined
Length: 20min 19sec (1219 seconds)
Published: Thu Jul 30 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.