We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Building Secure User Interfaces with JWTs (JSON Web Tokens)

00:00

Formal Metadata

Title
Building Secure User Interfaces with JWTs (JSON Web Tokens)
Alternative Title
Build Secure User Interfaces Using JSON Web Tokens (JWTs)
Title of Series
Number of Parts
133
Author
License
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
With new tools like Angularjs and Nodejs, it is easier than ever to build User Interfaces for the systems that you manage. But how to do it securely? Web browsers are woefully insecure, and hand-rolled APIs are risky. JSON Web Tokens (JWTs) are being prescribed as a panacea for webapp security, but you need to know your security basics before you can implement them with peace of mind. JWTs are a great mechanism for persisting authentication information in a verifiable and stateless way, but that token still needs to be stored somewhere.In this talk, Robert Damphousse, lead front-end developer at Stormpath, will explain the security loopholes in web browsers, and what you can do about them – keeping your JWTs safe and secure. Topics covered include: Web browser security issues like XSS, user credential security, managing access control information, Man in the Middle attacks (MitM), and Cross-Site Request Forgery (CSRF). How you can mitigate potential security risks. Security issues and implementation tips across the entire stack. What you need to know about cookies. Infrastructure issues with session identifiers. How to issue JSON Web Tokens (JWTs) to secure the browser application.Robert will demonstrate these points with a simple single-page-application, built with Angular.js, and backed by a REST API.
36
61
Thumbnail
1:11:04
73
107
Token ringSoftware developerUser interfaceUniform resource locatorSlide ruleUser interfaceInformation securityBitBuildingSlide ruleFigurate numberToken ringWeb 2.0Real numberMultiplication signUniform resource locatorShared memoryForcing (mathematics)Software developerTwitterWordJSONXMLUMLComputer animation
Software developerStack (abstract data type)Scripting languageJava appletSoftware developerSinc functionCartesian coordinate systemData storage deviceFitness functionCloud computingInformation securityMultiplication signBitProcess (computing)Kolmogorov complexityPoint cloudDescriptive statistics2 (number)Computer animation
Software developerIdentity managementJava appletAuthorizationAuthenticationDisintegrationActive DirectoryFreewarePlanningPoint cloudData storage deviceDatabaseInformation securityAuthenticationService (economics)ArmLevel (video gaming)Ultraviolet photoelectron spectroscopyLink (knot theory)Directory serviceComputer animation
Information securityAuthenticationHTTP cookieInformation securityHTTP cookieMereologyLink (knot theory)BitSampling (statistics)IdentifiabilityCartesian coordinate systemWeb applicationSoftware developerSoftware repositorySlide ruleWeb 2.0Uniform resource locatorData storage deviceKey (cryptography)Fluid staticsCountingDemo (music)Basis <Mathematik>Annulus (mathematics)Computer animation
Data structureMobile appSingle-precision floating-point formatWeb pageRepresentational state transferIntegrated development environmentClient (computing)Web browserInstance (computer science)Mobile WebMobile appWeb browserBlock (periodic table)ArmInstance (computer science)Scripting languageVariety (linguistics)Software development kitUser interfaceDifferent (Kate Ryan album)Parallel portRule of inferenceClient (computing)Integrated development environmentHTTP cookieJava appletService (economics)Cartesian coordinate systemProcess (computing)Web 2.0WordMobile WebFront and back endsRich clientBuildingChainComputer animation
Software developerInformation securityClient (computing)MalwareInformationZugriffskontrolleInformation securityMalwareWeb browserInformationServer (computing)Integrated development environmentIdentifiabilityPoint (geometry)PasswordMultiplication signQuicksortBitDependent and independent variablesCartesian coordinate systemComputer animation
PasswordHTTP cookieIntegral domainIdentifiabilityPhysical systemFlowchartHTTP cookieWeb browserPasswordEmailSet (mathematics)InformationLoginDataflowDependent and independent variablesFamilyInformation securityComputer animation
HTTP cookieSoftware frameworkInformation securitySpring (hydrology)Rule of inferenceDatabaseIdentity managementGame controllerTable (information)Physical systemRule of inferenceIdentity managementInformation securityIdentifiabilityDatabaseNumbering schemeFood energyService (economics)Computer animation
Server (computing)Service (economics)HTTP cookieToken ringArithmetic meanGame controllerMultiplication signCache (computing)Rule of inferenceOnline helpIdentifiabilitySingle-precision floating-point formatDatabaseMikroarchitekturInformationService (economics)Heegaard splittingScaling (geometry)MultiplicationSet (mathematics)Reading (process)Error messagePhysical systemComputer architectureSemiconductor memoryComputer animation
HTTP cookieRight angleWebsiteBuffer overflowError messageMultiplication signReading (process)Stack (abstract data type)HTTP cookieMetropolitan area networkCross-site scriptingComputer animation
Transport Layer SecurityComputer networkHTTP cookieFlagWeb browserServer (computing)Web browserOperator (mathematics)Server (computing)Flag1 (number)HTTP cookieVirtualizationCloud computingData conversionString (computer science)MultiplicationWeb pageMoore's lawConnected spaceUniform resource locatorMultiplication signFacebookProduct (business)Service (economics)Bit rateScripting languageFilm editingSign (mathematics)FamilyType theoryBound stateCodePoint (geometry)Office suiteComputer animation
WebsiteReal numberCodeHTTP cookieInformation securityCross-site scriptingInformationDemo (music)Right angleCodeCartesian coordinate systemLink (knot theory)Slide ruleWebsiteWeb pageComputer animation
Streaming mediaDemo (music)outputError messageCartesian coordinate systemClosed setDemo (music)Exception handlingCuboidSource codeInformation securityWeb pageInformationCASE <Informatik>WordHTTP cookieComputer animation
Web pageDemo (music)HTTP cookieWeb browserHTTP cookieMedical imagingWeb browserSource codeCuboidUniform resource locatorString (computer science)Server (computing)Computer animation
Software developerContent (media)Escape characterServer (computing)Client (computing)outputForm (programming)CodeSoftware frameworkDynamic HTMLWeb browserIntegrated development environmentScripting languageConnected spaceInformationFlagServer (computing)Process (computing)HTTP cookieDressing (medical)Library (computing)outputDescriptive statisticsDatabaseContent (media)Markup languageParsingComputer animation
HTTP cookieAuthenticationFlagScripting languageJava appletIntegrated development environmentString (computer science)Web browserIntegrated development environmentHTTP cookieLink (knot theory)FlagLibrary (computing)InformationTouch typingServer (computing)Java appletScripting languageComputer animation
WebsiteExploit (computer security)Information securityWeb browserDefault (computer science)Web 2.0Medical imagingSource codeComputer animation
Computer-generated imageryWeb pageWebsiteHTTP cookieGame controllerComputer programmingConsistencyNumberParameter (computer programming)WebsiteService (economics)Medical imagingFamilyState of matterMetropolitan area networkQuery languageWeb browserUniform resource locatorComputer animation
WebsiteWeb browserHTTP cookieServer (computing)Heat transferComputer-generated imageryWeb pageDomain nameHTTP cookieParameter (computer programming)Web pageElectronic signatureWeb 2.0Heat transferForm (programming)State of matterWebsiteMathematical singularitySingle-precision floating-point formatToken ringWorkstation <Musikinstrument>Doubling the cubeKey (cryptography)Uniform resource locatorServer (computing)CAN busComputer animation
WebsiteToken ringHTTP cookieMobile appEmailMobile appToken ringWeb pageWeb 2.0SynchronizationEmailFront and back endsHTTP cookieForm (programming)Doubling the cubeSelf-organizationContext awarenessEvoluteComputer animation
HTTP cookieClient (computing)EmailLoginDecision tree learningStapeldateiComputer virusPasswordClient (computing)HTTP cookieDataflowLoginEmailException handlingDomain nameFlow separationToken ringWeb browserPoint (geometry)View (database)Cartesian coordinate systemInformation securityCASE <Informatik>Server (computing)Integrated development environmentMedical imagingRule of inferenceSineDefault (computer science)WebsiteFamilyArithmetic meanBlock (periodic table)CuboidComputer animation
HTTP cookieZugriffskontrolleEmailWeb browserError messageServer (computing)Token ringTime domainCloud computingWebsiteDomain nameUniform resource locatorEmailWeb browserToken ringServer (computing)CuboidMedical imagingHTTP cookieQuicksortParameter (computer programming)Rule of inferenceDisk read-and-write headArithmetic meanComputer animation
Dependent and independent variablesRule of inferenceServer (computing)Web browserMultiplication signDomain nameRouter (computing)Web 2.0EmailShared memoryOrder (biology)PlastikkarteSoftware developerComputer animation
Web browserEmailServer (computing)Java appletScripting languageProxy serverCAN busAuthenticationDomain nameEmailProxy serverCondition numberProduct (business)QuicksortHTTP cookieAuthenticationToken ringSheaf (mathematics)Web 2.0DataflowPoint (geometry)Computer animation
AuthenticationProof theoryToken ringFile formatPoint (geometry)Sheaf (mathematics)Front and back endsSpring (hydrology)File formatPasswordAuthenticationToken ringType theoryComputer animation
Token ringString (computer science)Data structureUniform resource locatorCryptographyElectronic signatureRight angleMereologyFrequencyEmailString (computer science)IdentifiabilityUniform resource locatorElectronic signatureCodierung <Programmierung>Computer animation
MereologyContent (media)CryptographyElectronic signatureEmailToken ringService (economics)Category of beingSpacetimeFigurate numberObject (grammar)IdentifiabilityAlgorithmPhysical systemElectronic signatureSingle-precision floating-point formatToken ringCartesian coordinate systemTape driveLine (geometry)Public-key cryptographyField (computer science)AuthorizationArithmetic meanKolmogorov complexityTimestampEncryptionCAN busCASE <Informatik>Set (mathematics)MereologyElectronic mailing listSoftware frameworkOffice suiteEmailDigital photographyType theorySlide ruleSingle sign-onMultiplicationComputer animation
Token ringServer (computing)Client (computing)Sign (mathematics)HTTP cookieHTTP cookieWeb browserData storage deviceEmailLocal ringWeb 2.0FamilyMobile appServer (computing)Moment (mathematics)AuthorizationNumbering schemeGame theoryInformation privacyTotal S.A.InformationInformation securityProcess (computing)Computer-assisted translationDescriptive statisticsClient (computing)Integrated development environmentAuthenticationSign (mathematics)Reading (process)Cartesian coordinate systemComputer animation
Service (economics)HTTP cookieService (economics)Product (business)Overhead (computing)DatabaseCASE <Informatik>Ocean currentServer (computing)Inheritance (object-oriented programming)Multiplication signKey (cryptography)Port scannerOperator (mathematics)Client (computing)Type theoryInformation securityComputer architectureCryptographyComputer animation
IRIS-TAuthorizationPasswordToken ringSoftware frameworkMereologyAuthorizationWordPassword1 (number)Token ringSoftware frameworkComputer animation
Token ringToken ringDefault (computer science)MereologyValidity (statistics)Physical systemClient (computing)AuthenticationAuthorizationService (economics)1 (number)Cartesian coordinate systemMathematicsInformationInformation securityNumbering schemeRoundness (object)Data storage deviceQuicksortSign (mathematics)Point (geometry)Reverse engineeringComputer animation
Demo (music)Local ringLoginServer (computing)Dependent and independent variablesHTTP cookieUser profileElectronic signatureToken ringLogicMobile appWordDemo (music)Position operatorMultiplication signCartesian coordinate systemHTTP cookieToken ringFront and back endsEmailCondition numberDependent and independent variablesFlagAuthenticationWeb browserTimestampPhysical systemPoint (geometry)InformationLoginProduct (business)Doubling the cubeProfil (magazine)Form (programming)Server (computing)Error messageService (economics)Roundness (object)Game theoryLogicMessage passingPasswordLevel (video gaming)DreizehnArmSlide ruleView (database)FamilyTerm (mathematics)Validity (statistics)Sign (mathematics)SineLatent heatFood energyProjective planeInheritance (object-oriented programming)Electronic signatureReverse engineeringComputer animation
Token ringStrategy gameScaling (geometry)HTTP cookieHTTP cookieSoftware frameworkComputer architectureWeb 2.0Token ringMonster groupInformation securityMechanism designMathematical optimizationIdentifiabilityTerm (mathematics)Stokes' theoremMultiplication signLink (knot theory)Message passingComputer animation
Information securityDatabaseAuthenticationSoftware developerLink (knot theory)Message passingHTTP cookieInformationAuthenticationTable (information)TrailEmailCASE <Informatik>Strategy gameKey (cryptography)QuicksortAuthorizationMultiplication signKnotCartesian coordinate systemDomain nameLibrary (computing)Computer chessMultiplicationWeightField (computer science)Control flowVideoconferencingService (economics)Channel capacityPoint (geometry)Price indexComputer animation
Transcript: English(auto-generated)
All right. We will get started then. So welcome. This is my talk on building secure user interfaces with JWTs, JSON Web tokens. Just a little bit of housekeeping real quick.
I put this up on slide share. So if you guys want to grab a picture of that, I'll write down that URL real quick. Let's just put that out there now. We've got a few folks coming in still too.
This is my first time trying this, so I'll be curious to know if it works. Yeah, it works?
Cool. All right. Okay. So let's just start off to tell you guys a little bit about me. I've been doing full stack development for about ten years since before it was called that. Back then it just meant I did everything and didn't say no. But now it's called full stack development.
Doing full stack with JavaScript since 2011, Node was still kind of new back then. But at the start-up that I was with at that time, it was a really great fit for us because we were building like rich front-end applications and so Node helped us iterate very quickly because our back-end actually wasn't super complex, it was kind of just
like knitting together a bunch of data sources. Right now I am leading JavaScript at Stormpath. I'll tell you a little bit about us. We're basically a cloud-based user store for developers. So think of taking all that user crud out of your database and putting it in a secure cloud storage.
And you can use RESTful APIs, basically authentication as a service. We plug into a lot of things like Active Directory, LDAP and SAML. So it's my work in basically working with the full stack front-end to back-end that has really helped me put this talk together. And it's free to get started and you can use the free plan for pretty much all your
needs and then we can scale all the way up to even doing a private deployment in your AWS region. I want to give you guys kind of a high-level overview of all the stuff I'm going to hit in this talk because I'm going to get into some really technical stuff pretty fast.
So that's why I also wanted to give that link out early because there's going to be a lot of examples and little things. Basically if you've come for the JWTs, that's great, but we're going to get to that a little later because we're going to talk a bit about just general web app security stuff first, which inevitably means we're going to be talking about cookies quite a bit because
even though we'll talk about how to use JWTs in your app, we're going to be talking about how you can use cookies to store JWTs as well. As part of that, I'm also going to go over kind of like the traditional solution that we're used to using session identifiers for doing sessions and kind of talk about
some of the caveats there that JWTs help us with. And along the way, I'll be mentioning how this ties in a bit with Angular. In the end, I have a link to a GitHub repo that's a sample application, but rather than doing a live demo, I've just got a few static slides that I'm going to share there. Just a quick poll, how many people identify as a front-end developer on a day-to-day basis?
A few? Cool. So if you've been doing this a lot, some of this cookie stuff will probably be a recap, but for everybody else, I'm basically hoping to freak you out a little bit so that you'll go back and look at applications that you've built and reevaluate. Maybe there's some security loopholes here, especially around cookies.
So modern web apps, what do I mean when I say that? Well, it's kind of like the new stuff that's on the block, AngularJS, React, there's a few varieties of this. Basically, the idea is you've got a rich front-end application that's really JavaScript
heavy running in your browser, making Ajax requests to your back-end. Ajax, I put it in quotes, it's kind of like a misnomer because nobody really does XML anymore, but that's what people, people still use that word a lot to refer to the fact that your JavaScript client in your browser is dynamically talking to your back-end.
These days, these back-end services are usually JSON API, maybe you've built one yourself, maybe your back-end team has a legacy API that they've put a JSON interface on top of you, which is awesome, but in the end, this is what we're dealing with. Rich client in the browser, API on the back-end.
And we can find a lot of the parallels for this in non-browser environments as well. For example, there's tool chains that will build native desktop applications or native mobile applications that allow you to basically package up an HTML5 application for this other
environment, but really all it's doing is just running your application in some kind of browser instance, which is usually a webkit or if you're using a mobile phone, there's like different things going on there, but the idea is there's a lot of different places where HTML5 apps can run these days, and the cookie rules that we're going to talk
about actually apply for most of them. So what are the security concerns we need to think about for modern apps? Well, you have to secure user credentials. At the end of the day, somebody's going to log into your app, they're going to give you a username and a password, and you need to secure that, right? And on top of that, you're also going to be securing the server endpoints that people
are going to be talking to when they use their application. And because we're talking about browsers, we're talking about JavaScript, which means we need to prevent malicious code from entering into that environment, because it's actually really easy for that to happen. And then one other concern is with these rich front ends, you're going to want to give
them some way to know what they can access sort of proactively, because while your server can respond to a request and say, hey, you're not allowed to do that, if you can give the browser a little bit of information ahead of time, that just sort of helps you
render some user interfaces more quickly rather than waiting for a server response. So the traditional solution that we're used to in this world is to use session identifiers. And this is something that we're all used to, either we've built one of these systems ourselves or our underlying framer just handles it for us.
The idea is you send in a username and password in exchange, you give the browser back a session identifier, which gets stored in a cookie. So again, this is something that we're all pretty familiar with. You know, this is what it looks like as a flow chart. Submit login information on the response, the browser uses the set cookie header to
send down the session cookie. And then on all subsequent requests, the browser is going to automatically supply that cookie with that session identifier. This is okay if you protect your cookies. We're going to talk more about that. There's really nothing inherently wrong with this situation. You know, there's a lot of security concerns around cookies, but we'll talk about them.
In the scheme, you know, the session identifier is basically just a pointer. You go from your session ID to like a session table in your database, and then from there into your user identity. Possibly making yet another hop into some other system like Apache Shiro, which may have like a database somewhere, you know, to relate all the access
control rules for the user. You know, on the service, this is fine. But there are like a few caveats that you can run into. And we're going to talk later about how GWTs can sort of help with some of these issues. The biggest thing is that the session identifiers, they're pretty opaque. They really have no meaning to themself.
So every time a request comes in, you have to kind of do all this database legwork to go from this opaque ID down to the user information and the access control rules that you need to find. And if you're working in a multi-service kind of microarchitecture environment, where you're splitting everything up into microservices, you're suddenly
in this like funky situation where every single service that's going to like receive this identifier is going to have to go talk to your user database. So you can actually run into some scaling problems pretty quickly with just a really basic session identifier problem. You know, the most common way that we solve these things these days is to have basically some kind of cache up front, since you can have
an in-memory lookup between the session ID and the user information. And that's like, you know, that's a totally fine solution. That's just something we do architecturally these days. But again, when I get onto the GWT side of things later, we'll talk about how we can actually kind of bake some of that information into an access token so we don't even have to deal with having
like a distributed memory cache. Okay. Cookie is the right way, because there is a right way, actually. It just takes like hours and hours and hours and hours of like reading and trial and error and lots of time on Stack Overflow. Cookies can be compromised, it's true.
This is why they've gotten a bad rap. The three that are the most common that we care about are man-in-the-middle attacks, cross-site scripting attacks, and cross-site request forgery. CSRF, they're the last one I'm going to spend a decent amount of time on because that's the one that is not as well known as the first two.
But I'm going to go through each of these in detail. Man-in-the-middle attacks, those are the most obvious ones that make total sense to all of us. The idea is you're on Wi-Fi, your browser is communicating to a server somewhere, this cookie is basically being sent in clear text and it can be intercepted. There was a time way back when
when people's Facebook pages were getting totally destroyed because Facebook wasn't using HTTPS for cookies. So it was like totally easy for someone at a Wi-Fi cafe to basically just steal your cookies and basically be on Facebook as you wreck everything. It was pretty awesome. Since then, people have decided to spend money on computing power
so they can use HTTPS everywhere. Which is really the best solution to this problem. You should use HTTPS in production everywhere. And even on internal networks, if you're starting to use a lot of virtualized services, you should really interrogate how those things are being architected
because it's possible that internally, if you're using HTTP between multiple services, there might be some clear text leakage in there. So you might need to set up some kind of VPN-type stuff. This is a conversation to have with your ops guys or to read in the documentation of whatever cloud service you're using.
And finally, there's a really cool flag you can set on cookies when you're sending them down to the browser, which is a secure flag. At the end of your cookie string that you're sending down on the browser, you can just tack on secure to the end after a semicolon. And what that tells the browser is don't send this cookie if I'm not on a secure connection.
This is really important because when you get into complex ecosystems, where you've got single sign-on and you're bouncing the user around after a login, there's a chance that they might hit a non-secure URL somewhere in a redirect and at that point, the cookie would be leaked if you didn't have this flag on there. So this flag just tells the browser to only send cookies back to the server
if you're on a secure connection. Cross-site scripting. This is probably the one that everybody knows about because it's like the scariest one. And it is scary because it's a real problem. Basically what happens here is somebody finds a way to execute code on your site. There's a few different ways this can happen.
I'm going to show a particular example but this is the problem. Somebody manages to inject some JavaScript in your site which then starts to muck around with your application and either do requests on behalf of the user or basically just trick the user into doing something that is harmful. The OWASP guys have a really great article on this.
I would check it out. And Google also has really great information on this. The demo that I'm about to show you here in a few slides is from this link right here. So they've basically got this demo application that you can play with on that page. And this is sort of like the typical example we use
when we're talking about cross-site scripting attacks. What's happening in this application is it's kind of like your basic chat application. That's naively going to take whatever input the user is putting into an input box and course it into HTML and tell the DOM to evaluate it
and insert it in the DOM in a certain place. And, I mean, first off, just don't do that because it's bad. But if you're going to do it, there's some security problems. What can happen is if HTML is getting evaluated,
if the attacker can essentially put any information they want in here, they can trigger JavaScript by using this on error handler. And in this case, in my example, I'm saying alert document.cookie. So what's going to happen? They hit the button to submit this. The application tries to insert this into the page. The DOM has an error because this is actually invalid HTML.
There's no closing tag on the source there. And so it then triggers this on error handler, which, in my naive example, just alerts the session ID out there. Now, that's fine and well. But what if I wanted to do something more nefarious?
Well, imagine if I put this into that chat box. This is pretty crazy. What's happening here is I'm reading the document's cookies and basically just appending them to a source URL of an image. And the browser's going to comply and just say, great, like, you're requesting this URL. I'm just going to do it.
And you read the document cookies and appended it to that string. So great, here's this URL that I'm going to try to make a request, which basically means, like, I've got all your cookies now. And they're on my server, and I can basically impersonate you running scripts even outside of the browser environment. It's not good. So what do you do about this?
Well, first off, you don't evaluate HTML directly from user input. Just don't do it. Thankfully, a lot of the client-side libraries now basically prevent you from doing that, which is really cool. You can read the documentation, because they usually address this in there somewhere. On the server side, you also want to assert that any information
that got saved into your database, such as a document, doesn't actually have hidden markup in it that's trying to achieve the same thing. So there's really great libraries for this. It's just called content escaping, typically. So this is actually a pretty easy problem to solve, just as long as you're mindful of not straight-up parsing information
and using some libraries to help you with it. On top of that, there's another cool cookie flag you can use to also help you, which is the HTTP only flag. So similar to how you can send down that secure flag to say, don't use this on non-secure connections, you can also say HTTP only, which actually prevents the cookie
from being read from the JavaScript environment. So in that earlier example, where I was doing document.cookie to read the cookie string of everything that's stored from my domain, any cookie that's HTTP only will not show up in that string. So this is basically your best bet,
is to just use this to make sure that the JavaScript environment can't even read that stuff at all. So then the cookies basically become a private information exchange between the browser and the server, and JavaScript can't touch it. Same link as before, I would definitely recommend checking this out, and they also link out to a lot of libraries that are really helpful.
Okay. This one's my favorite, because it was new to me when I learned about it. Cross-site request forgery. It's taking advantage of things the browser does by default, very similar to the attack that we saw in the last example.
So in a nutshell, it exploits the fact that HTML tags do not follow the same origin policy when making GET requests. The same origin policy, we'll talk about this more later when we get into some more Ajax-based stuff. It's basically this thing that the browser has which says,
like, you're allowed to talk to this domain, but not that domain. It's pretty awesome, and Mozilla has a really great write-up on it. But HTML tags, like those simple image tags, don't actually follow that, because that wouldn't work, right? The web wouldn't work if you couldn't essentially pull in arbitrary sources from other places.
So here's what happens. The attacker actually puts some malicious HTML on a website that's not yours. So they manage to get the user to come to a website that they control. And what they can do is put, like, an image tag or some other similar tag in the DOM
that will basically just make this GET request to this URL. Now, this is kind of a typical example. You know, like, you've got this API. You can make a GET to with query params that transfers money between the two guys. Like, you know, I'm pretty sure nobody in this room is actually doing that, but stranger things have happened in the, like, browser world.
But that's the example. So what happens here? Well, again, the browser complies and says, the request is going to myapp.com, so I'm just going to send along any cookies that I have for that domain. So if you actually really have this API that allows a GET request with these two parameters to modify server-side state,
the server's going to, like, basically trust the cookies and the user it identifies and just do that transfer. It's going to modify that state. So this has to really be, like, combated against, like, because there's really no... Other than the solutions I'm going to show you, like, this is, like, very easy to do.
You simply just put URLs in your page. Even if it's a POST request, the malicious site can... If they can convince the user to click on a button, they can then use just a regular HTML-based form to issue a POST form request to the URL on your site. And your site, if it's not paying attention to these things,
it's just going to assume that it's, like, a legitimate request from this other website. So, again, like the XSS stuff, there are some known solutions to this problem. It just requires some implementation. The two you're going to find the most when you start looking on the web is the synchronizer token and the double-submit cookie approach.
The synchronizer token approach is mostly for more traditional apps where you have a page renderer, a form post, a page renderer, a form post. So I'm actually not going to talk about that. Under the hood, it's, like, the same situation as a double-submit cookie, but I'm going to talk only about the double-submit cookie because it applies to our context,
which is, like, modern apps with a rich front-end. And at the end, I'll also mention the origin header check, which is something you can throw in for sanity, but you shouldn't rely on just that. Okay. Double-submit cookie. So basically what happens here is you're going to give the client two cookies, the session ID that you were already giving,
and then a strong or random value. This is going to go in a separate cookie. And then the client is going to use JavaScript to try to send that cookie back in a way that actually does trigger the same origin policy. And the quickest way to do that is to send it in a custom HTTP header.
So let's take a look at our login example again. This is basically the same flow that we saw way early on. But now what's happening is when the user logs in and you send them the session ID, you're also going to send them a CSRF token and also seeing XSRF, those are kind of used interchangeably. And this token is basically just a secure,
random value that can't be guessed. Then on Ajax request to the server, in this example, making a get to the slash profile route, what the JavaScript environment is going to do is add a custom HTTP header. In this case, we're calling it XSRF token. And so then all your server needs to do is just say,
hey, is this cookie value the same as the header value? Because what we're taking advantage of here is the same origin policy. The browser is only going to allow JavaScript to add that header if the request is on the same domain. If it's on separate domains, the browser is going to block it. It's a security exception. So just by doing this check,
it's a real foolproof way to have a sanity check. Hey, is this request coming from my domain? If so, I can reasonably assume that it's coming from my application running on my domain. These particular header names are actually supported by Angular. I mean, you could essentially use any header name
and cookie name you want, but Angular by default, if it sees a cookie called XSRF token on every Ajax request, it's going to automatically append this HTTP header X dash XSRF token. So it's kind of like a standard now maybe, because Angular does it.
But again, the names can be arbitrary, but if you name your cookie as such, Angular will automatically append that. It's like one less little thing you have to do. So this is the success case. Let's look at what this looks like from the attacker's point of view. So in this situation, these little red boxes are sort of like,
imagine two separate websites that are malicious. In the first example here, they're trying to use that image tag-based thing, or they're just trying to make a get request to this URL that takes parameters. So the browser is going to send along the session and the XSRF token cookie,
but because this is like a naive get request, it's not going to append that custom header. So when your server does your check, does this cookie equal the header value? No, because the header value is not there, so it's just going to fail that request. Similarly, let's imagine something really crazy's happened, and the attacker somehow got access
to that XSRF token cookie value, and now they're trying to basically manually send that in the custom header. Well, that's not going to work either, because the browser's just going to straight up stop that from happening. It's going to say, you're trying to make an Ajax request to this other domain and set a custom header?
I don't allow that. It's a different domain. Now, there's one thing you need to know about here. This is a CORS warning. So the same origin policy gives you a way to modify its rules. Your server can basically tell the browser certain domains
that the browser can cross-communicate between. It's called cross-origin resource sharing, as a CORS stands for. You've got to be careful, though. When you start reading on the web, people are going to say to do this, which is to wildcard these things. Don't ever do that, because you're basically going to undo the whole same origin policy. It may be convenient during development,
but it's a really dangerous thing to do. So any time you see that, just stop and be like, okay, I have to manually define them. It's okay. So be careful of that. Finally, the origin header check is something useful. So browsers, like IE8 and above, I think,
send an origin header, which basically just says, well, what domain is this request coming from? And it's useful. It can't be modified by JavaScript. It's reliable. But it can be modified by a malicious intermediate proxy. So again, this is another reason why you should just always be using HTTPS on all your production stuff.
Okay. So we got all that out of the way. Like, that's sort of my soapbox, like, before I even get to the JWT stuff is, like, those are all the things you need to know about cookies, because we're going to be using cookies with JWTs. So you just got to be aware of all those cookie issues.
Now, token authentication is big. You know, if you start reading about this on the web, there's so many things going on. There's JWTs, there's access tokens, refresh tokens, OAuth2 workflows, like, all that kind of stuff, and it's, like, so much. So the point of, like, the next section here
is to kind of, like, take all that and just, like, solidify it down to something, like, grokable and show you the pieces that really matter if you just want to take advantage of JWTs for securing your frontend. So in a nutshell, this is it. Authentication is proving who you are.
It's providing that password and saying this is me. A token is a way of persisting that proof. The JWTs that we're going to talk about, in a way, really aren't that different from the session IDs that we were talking about before. You're just exchanging credentials for a token that persists that assertion, because you wouldn't want to type in your username
and password for every single request that your frontend's making to the backend. JWTs are simply just a token format. You know, they're an RFC which describes a structured way using JSON to have, like, a meaningful token that can have, basically, arbitrary data inside of it. And they're often used with the OAuth2 workflows
for access tokens and refresh tokens. They're not... The OAuth2 spec doesn't specifically require JWTs. It's just a very convenient format. So that's why you start to see these things coming together. And in short, they're fun. So let's go. We're going to dig into them now.
If you counted them in the wild, they basically just look like an ugly string, right? It looks no different than the session identifier. So at first glance, you might be like, well, how is this different? Well, it's more than just an ugly string. It's an ugly string with two periods in it that's separated out into three parts.
You've got a header, a claims body, and a cryptographic signature. And note that it's a base64 URL encoded, which is actually a little different than the straight-up base64 encoding. You'll lose hours on that. So once you decode those parts,
now I get to look at the cool stuff. The header is basically describing this token. In this case, the type is JWT, go figure. And the algorithm that was used to sign the token was the HS256. You can also see some other properties in here that describe the compression and the encryption of the token, if you're doing those things.
The body is a set of claims that I'm going to dig into in the next slide. And then the signature is just that. It's the signature that you can use to determine, like, okay, given a private key that I have, was this thing signed by me, by my service? So the body is where all the fun happens.
Now, when you're looking at a JWT body, it's arbitrary, you know, it's just a JSON object. You can put whatever you want in there, whatever makes sense for your service. But when you look at the RFC and in practice, you're going to see these four fields most commonly. The issuer is describing who issued the token.
It's usually some kind of, like, URI that describes an application. When you start to get into, like, multiple applications and single sign-on kind of stuff, you'll be using the issuer field to say, like, okay, this came from this application versus this one. The expires field is just a, you know, a Unix timestamp telling you when this token,
when it stops being valid. And the subject tells you who it represents, which will just be some kind of user identifier that makes sense to your system. And the scope claim is where we start to see some overlap with OAuth. And OAuth is an authorization framework, which basically means, like, it's concerned with, like, granting access to certain things.
And so when you're using these tokens to basically persist these assertions, OAuth 2.0 calls it a scope, which is basically a space-separated list of things the user can do. So in kind of, like, our photo example here, the scope would mean that I can access data about myself
and our BY API. This is all just stuff that will make sense to your system. It's really up to you what you put in here. There's no, like, pre-described things. So who issues JWTs? Well, in short, they're issued by your server. And they're gonna be signed by a key that's private to your server. And then once you create them and sign them,
you're gonna hand them over to the client. We're gonna talk about how to do that with cookies, but with, like, a mobile application, a native mobile app, you might use, like, some of the secure storage APIs that are sandboxed to that particular application. Yeah, storing JWTs. So in the browser, let's talk about the browser.
When you start to look on the web, reading about JWTs and browsers, you're gonna see people putting them in local storage. But do not do that. Local storage has a lot of problems. It doesn't follow the same origin policy in the same way that the rest of the browser does. And because it's a JavaScript API, it's vulnerable to cross-site scripting attacks.
So all that stuff we talked about, hiding cookie data from the JavaScript environment is totally undone by using local storage. So just don't do it. Really, your best bet is HTTP-only secure cookies. That's really the best way to have private information in the browser that's used for authentication.
And conveniently, as we've seen, cookies provide an automatic way of supplying the token on requests. When you see people using the local storage scheme, what they'll also do is supply the JWT, the access token, in the authorization header. So they'll use AJAX to manually add an authorization header
where the value is barer, and then the token, the JWT. That's nice and cool, and it feels fun, like we're doing new stuff, but it's actually not safe. So really just rely on secure cookies to do that. But as we saw, cookies have that CSRF problem, so you gotta mitigate that as well.
It's this little cat and mouse game of trying to have private data in the browser. Now, verifying them. So great, the client has them, they're stored securely. On request to your server, the client's gonna supply them, in our case, via cookies.
And there's something super awesome here, which is that we can implicitly trust them because they've been cryptographically signed with a key that's private to our service. So this is pretty great because it allows us to, you know, lose a lot of overhead of running back to the user database or the session database all the time. We can just, boom, do a quick crypto check
with a private key and be like, okay, this person is who they say they are, this token is issued by me, and here's the scope of the things that they can do. So because it's structured like that, it enables some really interesting interoperation between services, and it kind of just gives you some more possibilities if you're doing
a microservice type of architecture. JWT plus OAuth, this is where it gets fun. I like this part. So OAuth 2, RFC6749, that's the most recent one, I hope, is an authorization framework and a good sleep aid.
So if you've ever come back from lunch and you want that little 15-minute siesta at your desk, open this, start reading it, and you'll be out before you know it. But if you make it through it, you can give this talk, which would be awesome. And about halfway through it, you'll find this thing called the resource owner password credentials grant.
Well, in other words, that's just exchanging a username and password for an access token and a refresh token. It's like the new fancy way of saying, like, you're gonna give me credentials, I'm gonna give you something back that you can use for subsequent requests. Now, the access token and refresh token, this is where it gets a little hairy, and I'm gonna do my best to attempt to describe this
because it can kind of get a little unwieldy. But think of it this way. You've got these two tokens. One's got a shorter lifetime than the other. The access token is a shorter one than the refresh token. The refresh token is used to obtain new access tokens as they expire.
So the client needs both of these. You know, there's often a little confusion, which is that having the two tokens, sort of like security through obscurity, gives you more security. That's not true. This is actually just giving you some interesting trade-offs of how often you kind of want to make, like,
a full round trip to your authentication service. What you're gonna do is, as we talked just a few minutes ago, the access tokens being the signed GDBTs are basically stateless. So you can just quickly say, like, verified, verified, verified, okay. But, you know, at some point, something about the user's gonna change, right?
Like, maybe their account gets disabled, maybe they get access to a certain part of the system revoked, their scope changes. So occasionally, you do need to make a round trip to your authentication service and your authorization service to, like, you know, just sanity check, like, okay, what's going on with this user? So with this scheme of the access tokens
that expire before the refresh tokens, you get this, like, nice little lever where you can control how often that happens. So if you're, like, a really, really, really sensitive application, you might do something like make your access tokens valid for a minute, and maybe the refresh tokens for an hour.
So, you know, like, every minute, you're verifying that the user's okay, and then every hour, the whole session just ends, and they have to re-login. In practice, though, if you don't need that much security, what we do as a default with Stormpath is we give you an access token that's valid for an hour, and the refresh token is valid for a month. So you really only have to re-authenticate once a month.
Other applications that really don't store personally identifiable information might do access tokens of a month and refresh tokens of a year. You know, it really just depends on your situation, but what's nice is that this scheme just kind of gives you a lever to control how often you're gonna make a round trip to your authentication service.
Demo time. I'm actually gonna leave it up to you guys for later to dig into the actual code, because live demos are always a disaster. But I'm gonna walk through what this application does, just to kind of, like, highlight how you can use ideas from JWT and OAuth together
between your front and back end. So Angular app with login form. Awesome. Just take my word for it that that's an Angular application, because it is. So when the Angular application posts the login form, it's gonna send along the origin back to the server that's relevant for what we talked about earlier,
and then the username and password. This is super straightforward. But now here's what's different. Take a look at the cookies we're sending back. We're gonna send back an access token and a refresh token. We're gonna give both of these things to the client. We're specifying HTTP only on them. The secure flag is missing, because this is local host,
and we don't have secure, but you need that in production. And also omitted from this is all the CSRF cookie header kind of stuff. I pulled it out of the slides, because it was too much, but don't forget about it. And also, if you look in the timestamps here, you'll see the access token expires 13 May, the refresh token a month later.
So again, you're seeing this play out. You're gonna want to set the expiration times of your cookies to the same as the tokens, just because then the browser will automatically purge them when the time comes. So that's what the server response looks like. Now let's look at a subsequent request by this application.
We've logged in, we've got our tokens, now I'm navigating to my profile view, so I'm making this AJAX request back to the backend to get some data. Well, the browser is just gonna do its thing. It's gonna supply both cookies back to the server, at which point the server has a little logic thing it's gonna do.
It's gonna look at the access token first, specifically the signature and expiration. It's gonna double check that, yes, I signed this token, it's from me, and no, it's not expired yet. If that's true, great, we can allow the request. I mean, super simple, right? We already know who the user is and what they're allowed to do, so I can use that information without having to look it up.
If that's not true, if the access token is, if it's expired, we're gonna try to use the refresh token. If it's invalid, you should just straight up reject the request and delete the cookies, like something weird's going on. If you ever get to a point where a token is not signed by you, it doesn't pass that validation, it's like game over, basically.
But assuming that's not true, it's simply just an expired token, or it's missing because the browser's already expired that cookie, we're gonna try to use the refresh token to get a new access token. So, you know, this will depend on, this round trip to the authentication service will depend on what you're using internally.
This particular application is using the storm path service as the whole authentication system, but it could be whatever system you use. Point is, you're just gonna double check that the user's valid, and if that's true, you're gonna basically issue a new access token that you can send back on the response. You're gonna authenticate the response,
also send down this new access token, so that the next request will have that access token. If that didn't work, you know, clearly, there was a rejection from the authentication service, and you're just gonna reject the request and delete the refresh token cookie. How you deal with the responses, it's kind of up to you, but typically a 401 response is used generally
for any of these error conditions. You might optionally use a 403 if it's very clearly an error of forbidden access. Okay. I mean, that is essentially the talk there. You know, just trying to give you a high-level introduction to what GDBTs are,
what it means in the whole landscape of all these terms being thrown around like OAuth, and I'm basically just telling you, like, cookies are an okay place to store access tokens. You just, you gotta do a little work to make sure the cookies don't get stolen, but that stuff's actually pretty trivial. Like, pretty much every web framework these days
has a mechanism for managing things, like the CSRF tokens and all that. You just gotta go find it in the documentation and turn it on. So, yes, quick recap. Cookies, secure them. GWTs are an improvement on the opaque session identifier. They're not really like some amazing new technology
that's gonna solve all your problems. It's an improvement that mostly gives you some interesting optimizations for your microservice architectures. And the access token and refresh token stuff from OAuth 2 is useful if it hasn't already put you to sleep. So with that, I mean the Cookie Monster's Day.
Thank you for dealing with all that annoying stuff about cookies. At this point, I'm gonna open it up to questions and just leave up some links for Storm Pass that you can check us out. A lot of the stuff that I've talked about is baked into all of our libraries, so if you wanna use us as your authentication backend, you can basically get a lot of this for free.
Okay, thanks. Questions? Yep.
Yeah, so you're sort of thinking sort of like a multi-tenant situation where you might have multiple subdomains on the API. Yeah, I mean, there are a few edge cases where you do have to kind of open it up like that,
but at that point, you might wanna consider that's where the tables start to flip and then it might actually make sense to go the other way and start using the authorization header and not sending things in cookies. It's an interesting trade-off. So if you somehow get into a situation
where you have to open up an API essentially to everybody, then the tables basically flip over to using the other scheme, yeah. Cool. Yeah.
Not a whole lot myself. I can just say that generally speaking, OAuth 2 describes a whole bunch of strategies for which you evaluate those assertions and either reject or pass things through.
It's pretty complicated, but if you're tasked with basically implementing authorization in your application, it may make sense to look at it and see if it fits your needs. If you have a specific application, we could talk afterwards and I could give you some insight.
Yeah, there is a KID field,
which is commonly being used right now in your tokens, where you basically have some kind of like non-sensitive key that identifies the key that was used to sign it. So that's a way you can bake into the token some information about who signed it and you can kind of back your way into which service. Does that kind of answer that question?
Could possibly be that as well, yeah. I know it's like late. It's like the second to last track on Friday.
Well, I will chat some more, but if there's no other questions, coffee time for everybody else. All right, thanks guys.