 Good afternoon. Hope everybody's excited to be here. I'm in bright lights in big city. My name is Adam Englander. I'm an engineer at Iovation. And I'm here to talk about something that we've recently done using Hose to secure our REST API. So first, I want to give a little bit of a background about myself and APIs. So maybe you can hopefully think I know I'm talking about a little bit. So this is what I look like when I started writing APIs. That was a long time ago. It was so long ago that soap was the new hotness. That was a long time ago. And my career, I've actually spent, which is kind of odd as a PHP developer, I spent more time in my career writing APIs than I have building websites. So since 2001, I've been working on a lot of different APIs. My first one was a global authentication service, although that was Java. And then I started doing a lot of stuff with APIs in PHP with a loan application PingTree and a loan management system. Worked on an advertising network API, which is really my first attempt at a really high volume API. And then a real-time loan risk assessment system, which was an API that just talked to other APIs. So I got to experience how difficult it was to make a good API. And at the same time, consume other people's terrible APIs. And in 2015, I started working for where I'm working now, which is LaunchKey Now Iovation. And I work on a decentralized multi-factor authorization API, it's a lot of words. And through this time, some are more secure than others. I'm a little embarrassed to say that I was in fintech and I was working on actual financial stuff. That was nowhere near as secure as it should be. I thought I was doing the right thing. When I started to work for an actual security company, I learned just really how bad it was. But neither of those were hacked. So, and they've gotten better since I left, so I don't feel too terribly bad about it. But in all of these APIs, and maybe you've experienced this yourself if you're writing APIs, auth and crypto was messy. When you add the auth to the message, it adds complexity on the backend, where you have to be able to parse the message to be able to just deal with the fact that someone is giving you credentials. When you remove it outside of the message, you lose context. You're not quite sure what's going on with what it's actually trying to authorize for. Every implementation was specialized. Every time you did it, you did it differently. It depended on what the application was doing, what you needed to accomplish. So every time, even in the same company, when I would move from division to division or just one app to another in the same group, how they did authentication was different. How they did encryption, if they did it at all, was very different. How you validate the request and the response was very different. And crypto was non-standard and static, which meant that if you wanted to upgrade your crypto, that you had to completely change your API, which is not great. Because if you've been working in development for a while, you know that, hey, when I started working with PHP and that 2005 API, it was perfectly okay to use things that we would not consider safe now. Absolutely fine then, terrible now. I mean, there was a time when a SHA-256 password was considered super safe. We know that's just not the case today. And the worst part about it is that non-experts, like myself, had to write a lot of code that dealt with cryptography and signature verification and message validation and authentication authorization, which is not great. I'm not a fan, and I was not a fan of doing it there and having to learn everything, but the little bit that you can pick up trying to figure it out isn't super helpful. So for me, 2015 changed all of that. IETF RFC 7523, it may not mean much to you, but it meant a lot to me. And that is the JSON web token profile for OAuth2 client authentication authorization grant. Big, long word. But what that meant is that JavaScript object signing and embedding or encryption went mainstream. And this talk is primarily around Jose, which is the JavaScript object and signing encryption. And the reason it was such a big deal is that this was an RFC where authentication, authorization, encryption, data integrity validation are not tied to the protocol. So if you look at all these other RFCs, they're all basically tied to if you're making this kind of request, then this is your authorization. It's very rare that you have a gigantic specification that's not based on single sign-on that is around how to encrypt data, how to transmit data, how to verify and validate information, how to authorize and how to authenticate. It has nothing to do with the underlying implementation. And it was used initially for OAuth, OAuth 2.0. It was added as an implementation for OAuth 2.0, which then became OpenID Connect. OpenID Connect is based on that. It was also actually a little earlier on adopted by Fido. And if you don't know what these things are, it's not a big deal. It's a big deal to me because if you add in one more acronym called SAML, that is every authentication protocol in the modern world. So with the exception of SAML, which uses some terrible XML, all these other things use Jose, this JavaScript object signing and encryption. And because they did that, what they did is they created, I mean, there's a lot of IETF standards, but they added credibility, stability, and longevity. OAuth is not going away. OpenID is not going away. Fido may or may not succeed. We're still finding out. I mean, my company's a member of the Fido Alliance, but nobody's ever actually brought anything out really big. But this meant that I could use this without worrying about whether it's going to go away, if it's going to change drastically. The fact that when you log in with Facebook, you're using Jose tells me that I don't have to worry that they're going to have some gigantic breaking change when they find this little bitty bug that destroys the world with security. So that was exciting for me. And so when I got that, we decided that we wanted to use this inside our launch key product. And a lot of this talk is about the case study on what we were, what we became, and how we went about that using Jose, because it really transformed our entire API. And to give a little background, so launch key is a multi-factor authentication and authorization service, which means you use us to authenticate, which means it needs to be super secure. It's got to be super secure. And so version one, the before time, started off about four years ago. And the data was rest-ish. It was a really poor representation of rest. Didn't really use HTTP status codes very well. Put a lot of terrible things in the query parameters that broke the 1024 master protocol limit. It was mostly form-encoded requests, mostly, not all, for post-put and delete, and it had JSON responses. So the data was kind of a mishmash, depending on what got slapped on here and there. Sometimes you even had credentials in the, in the, when you're passing JSON, there's, I think there's one endpoint in the old one that passes JSON as the data, and the encryption signature is actually in the query parameters. It's really, it's really unpleasant. But it still exists today. Credentials, so it had siloed credentials for entity types. So if you needed, if you had two different things you were interacting with, an organization level or an application level, you had two sets of credentials, and you just had to use, know which one you're gonna be interacting with. It used random integers for identifiers. Passwords were sent in an encrypted package. And password rotation with old passwords expiring one after the new password was generated meant that we'd have to hash for your new password and your old password, and if one of them was good we were okay. Wasn't great, but it worked. And for cryptography, we had good cryptography. It was RSA OAP 256. We used AES 256 CBC, and had really good shot 256 RSA signatures for portions of the package. But because of the limitations on what you could encrypt using RSA, sometimes you did it in AES, which meant that you had you had to have a shared secret for that to actually be work because it's symmetric encryption. And some of it, which was most of the application interaction, was using RSA for encryption. So sometimes it was one, sometimes it was the other. You never really knew. And on the security side, it used, did replay prevention using a requester ID and a timestamp. It did signature verification on the pass for the timestamp only, because that was the encrypted part. It encrypted the pass for the timestamp, and it rate limited by user ID and subject. So the good part about this API is that it was really secure. The API was never compromised. We had a bug bounty for four years, and it was never compromised. It passed a ton of static and dynamic analysis by top security firms, and even, we were recently acquired and we were in the acquisition market and had been evaluated by some very large security companies, and we passed all their tests because no one's ever been able to fabricate an authorization, which is fantastic. But what we care about in this room, can you use it, right? It was terrible for usability. Before I was working at LaunchKey, I know some of the developers there. I've worked with them at the FinTech job, and we had a little hackathon. I was like, oh, I'm gonna write you an SDK. And I spent a day in their office trying to write an SDK, and I did not finish in a day writing an SDK because nothing was the same. Depending on what call you made, depending on how the data was set up, the encryption was different from call-to-call. It was not restful. It's kind of bizarre. Too many credentials to manage. I heard that a lot. So when I started working at LaunchKey, my job was to help implementers implement our SDK. And no one could figure out which I would get these chats and these emails of people having problems, and they're using the wrong keys in the wrong place. Well, that's not their fault, right? That's my fault, because it's a terrible, terrible way to go about it. And there was no way to properly rotate your credentials. So if your RSA private key, you're afraid that it might have been compromised, you need to change it out, you're gonna have downtime, because you've got to go change it in your code, you've got to go change it on our server. One of those is gonna get done first, and you're gonna have downtime, which is bad. So we moved to version two. It was almost awesome, but it was an attempt at making it better via open standards. And that's where JSON WebToken came in. It's the first time I really actually looked at it, because our lead engineer said we're going to use this, and we're gonna use this on the mobile side, because that's what we had a lot of control over. We have a mobile app that we interact with. So we said we're gonna use JSON WebToken to do signatures and all this type of stuff with requests back and forth for the mobile side, and we'll eventually move everything else to that. And what it gave us is that we started using an open standard for data security. We added private claims for a hash of the body, so we had a much more, a way better validation process, and we had a more secure API request format, which is all fantastic. JWT does these fantastic things for you. But we're still missing things. We were still using custom and inconsistent encryption, because we weren't using JWT. We didn't increase the restful quality of it. We didn't sign the entire request. We just did the body. I'll get into that in a little bit. And we did not reduce the quantity of credentials, and we didn't improve the response. So the response just kind of came back and you had to trust that that was the response you were expecting, that someone hadn't given you a man-in-the-mill attack. Now, on our mobile device, it's not a big deal. We do certificate pinning, but on the other side, for APIs, as an implementer, doing pinning isn't a great thing to do if you don't know how to do it, and it can be problematic when search change, and you have to be kind of up on that. So we came up with API three, who were acquired, and we were told that we had to move from processing, I think it was 3,000 requests an hour to 10,000 a minute, which meant we got to rewrite our API. And when we were rewriting our API, we decided that, well, let's do this right. Let's go version three, and we're gonna actually do the security stuff right because since we're rewriting everything, let's not make it hard. So what we changed is everything. So we used JWT, JSON web token, with custom claims to validate the entire request and critical portions of the response. We used JSON web encryption to encrypt the request and the response. We used JSON web algorithms to future-proof our cryptography. We used JSON web keys for credential rotation, and we removed that little password that we used to send in the encrypted thing altogether because it wasn't necessary anymore because we could validate all that stuff with RSA. And we got some immediate benefits on the development side because we're able to decouple authorization, authentication, and validation of requests and responses with the actual controllers. So we're able to move all that to middleware. So when we had to write tests for our controllers because you're doing all this encryption, and encryption, decryption, authentication, signatures, validating signatures, that's a lot of things that you're doing before you even start processing the request. But all of those pieces were part of the request coming in, so they were tightly coupled. And so now with Jose, you're allowed to separate that out where you've got this data that's part of your request that still has context, but it's not part of your actual request packet. And so in a spoke of genius, we decided we'll move it to middleware so that all of our controllers deal with is the fact that I've got a JSON request for an endpoint, and that's it. All the decryption, signature validation, determining what entity is making the request, determining that it has access to be able to do that, all that happens in middleware now from all the information that's provided in the JWT. And that gave us way better unit testing. I don't have to mock 600 interactions before I actually get to the code I'm trying to work with. We had controllers, and it's not all of security's fault, but we had controllers that were hundreds of lines long, hundreds of lines long before it got to a single service, hundreds of lines. It's really difficult to test that. And moving all of this stuff out made it so much easier to just add new functionality. It would take days to add an endpoint in the old system. In the new system, it's usually, if the service is already written to interact with that part of the data, it takes us 20, 30 minutes to write a new endpoint to be able to interact with existing functionality. So if I need to move it from this part of the, this level of the API needs to interact with a particular service, and another level needs to do it, it's just super easy. I know I've already got the validation verification, I know if they have access to the URL, so I don't have to worry about that. I've got the entity interacting, and I just perform the interaction. It is really, really streamlined, and it's really, really awesome because it was really difficult to make changes. The other good thing that I'm super excited about, OSS libraries, I can now test my API, full integration test, without having to use my client SDK. It was so hard to write all of the code to do the signature creation and verification, validation, encryption, all that type of stuff, that the only way that we could test our own systems was using our own SDK. So if we introduced a bug in our SDK, our test would fail or not, which was actually worse, the client SDKs became less complex. I don't have to write all this information for doing signatures and encryption and decryption, and OSS contributions are actually possible now. We have, I think, one contributed decent SDK out there that the community has contributed, it's a go SDK. But speaking from my own personal experience of trying to do that, I tried to implement a launch SDK, and I couldn't do it, and I had the developers in the room with me helping me, and I still couldn't do it, not in a day. And another one, I write all the documentation, I'm transitioning out of that, thank goodness, but documentation complexity was reduced. You're just using this library that's already documented somewhere else, super helpful. The other thing that it does is it creates uniformity across our APIs. So now, in our organization, we're completely switching to Jose, we've got all these different ways to do authentication authorization, but as an organization, they found out what we were doing, and in the review process, because we do peer review across groups, they said, that's a way better way of doing this, we're all gonna do this. And we actually, because we work together, we can help with a much better solution, which gives us shared knowledge, because if you move from group to group, trying to figure out how you're doing auth is usually pretty tough. And now we also have the option for federated authorization. And the other good thing is that because of the way that JWT works, is it allowed us to, using its own internal workings, use hierarchical authentication, because JWT has this idea of an issuer, and a subject, and an audience. And so what we're able to do is say, hi, I'm ABC organization, I would like to make this request for application one, two, three. I've got an issuer, I've got a subject. Inside of my middleware, without knowing anything else, I know that, oh, this is an issuer, this is a subject, I can determine if this issuer is allowed to make a request for the subject, and if so, I just pass it along, and my controller just knows that it has a subject entity. That's all it knows. It's just got a subject. And it also allows us to kind of change it however we want with our middleware. And JWK, JSON Webkeys, allows for identification of the credentials used. So when someone says, hi, I'm issuer ABC, and I'm using this key, I can go figure out what that information is, and if there's information that I need to do that's specifically dealing with this other subject, I know how to figure out which credentials to use for encryption, or validation, or verification, or whatever the case may be. And I can pass that from entity to entity to entity, and they all understand it. It's not something special that we did. The mobile side does this, and the app side does that, before all of our stuff was that way. But there is some bad. Some languages have minimal support for algorithms and strengths. So we've had to actually submit pull requests for enabling AES 256, or sorry, RSA, OAP 256. It's not a requirement to be an implementation. It's an optional implementation. Some of them don't have it. Some languages have no support for JSON web encryption, like Objective C. We had to actually write our own minimal implementation for the stuff that we did. And unfortunately, we didn't find that out until like a week before everything was supposed to go live, there was an implementation. But the good part about it is, is that there's some good documentation on that, that we have the tests that were necessary to actually write the implementation. So in the RFC, there's enough information that you can actually write an implementation and know that it works, which is really nice. And there's some good documentation, but unfortunately, as I discovered, you have to get a good working knowledge of RFCs. You have to be able to understand how they talk in RFCs. And if you've never done that, it's a little weird. But once you get it, you're like, oh, that makes perfect sense. And so that's what we did and why we did it, but how we did it is the really, really, really cool part. So we did it with Jose, Jose and Jose, right? It's all Jose all the time. We really, really jumped in headfirst, and it was super important. And if you don't know what Jose is, it's, like I said earlier, the JavaScript sign and encryption, but it also, it encompasses a bunch of pieces that are their own little worlds that would make up Jose, which is the JSON web token. I know he's here somewhere. There's somebody giving a talk about, there he is. Luis is giving a big talk about that tomorrow. So I'm not gonna get super in detail about JSON web token. If you, once you see my thing, like this is something I really wanna do, go see Luis's talk and he'll tell you all about the JWT, because he actually writes one of the libraries. JSON web signature, which is for signing data, right? It's not signing any particular data, it's just signing data. JSON web encryption, again, is just for encrypting data. It doesn't matter what type of data it is. JSON web algorithm and the JSON web key, which I misspelled with KW key. JSON web algorithm is basically just a list of predefined strings that identifies what you used. So if you're using AES encryption, most of us probably use AES encryption, you're probably using 256, 34, 512. Well, sorry, PHP is 128 or 256 most of the time. And you're probably, hopefully you're using CBC. You might be using something else. There's a little string that says I'm using AES. I used 256 key size and I used CBC as the mode. So that when you get the data, you know how to decrypt it, right? That's all about communicating what you did so that you can do what you need to do once you get the packet from the other person. And JSON web key is for identifying information about keys and you can even pass public keys along with the data. We chose not to do that. The JSON web token is actually just a JSON web signature that has a specialized payload. So in a JSON web signature, we'll kind of get into a little bit more. With a JWT provides credentials. There's an optional nonce that we use called the token ID. It provides timestamp information and duration for how long the request is valid. We were doing all of this manually internally. We're all these pieces here, credentials, nonces, timestamps and duration of the request. We did that, it was hard coded into our code and we had to document it for everybody else and that you could not change. If you'd say I only want this request valid for 30 seconds, too bad, it's five minutes, right? Cause that's what our code says. But we were able to change that using the JWT. And one thing that you are allowed to do is you can extend JWT using private claims. So we extended it using private claims to add additional data that were important to us, which I'll get into that in a minute as well. So JSON web signature has basically, it's comprised of three segments and that can be expressed in a JSON object which nobody actually sends around. Or you can do compact sterilization, which is three segments of URL, base 64 encoded data separated by dots, periods. And so you have a header and the header is common amongst JWT and JWT and it provides information about the key. So what key did you use to encrypt this, or I'm sorry, signature, to sign this? What key did you use to sign it so that I know which key to use to verify the signature? What signature algorithm did you use so I know to use the same one when I go to verify it? And also there's optional content metadata, which we also use to describe what's the information in the payload. Payload is the data to be signed and then there's the signature of the header and the payload. So you take the header, you take the payload, the little period in between, you use your algorithms that you specified, inside your header, you do a signature, you base 64 URL encoded and there it is. It's actually fairly simple. JSON web encryption is very similar, although it has more parts, and it's also how much data and it is dependent on what you do. It's extremely diverse in what you can, in the ways that you can do it, but we took it to the absolute extreme because that's our job. We're a security company with an authentication system that needs to be secure. And so again, you have the header, provides all that information, but it actually has two different pieces for encryption and algorithm, because doing JSON web encryption, there's a thing called a content encryption key. And what that basically does, and what we really loved about it, is that when you're doing content encryption, you can use AES encryption. So you're always using AES, right? Most people are familiar with AES, but the important thing with AES is that you have a random initialization vector. This library handles that. The other thing that it does is it generates a random key. So everything that you encrypt, it gets a brand new key every single time. And it's using RSA, which is much more secure than AES, but it takes longer, it has limited sizes that it can encrypt. It uses RSA to encrypt the keys. So you have the header information that tells you what you're using, you generate random keys and IVs, you encrypt the key, you put that in part of the packet, and then you make your encrypted data, and then you actually do an HMAC of all of that to get there. So the last pieces are the initialization vectors you used for encryption to payload, the encrypted payload, and then your HMAC, so that you can verify, it actually provides verification that yes, based on the key that's encrypted that people can't figure out, I'm going to sign all the payloads to make sure it hasn't been modified. One of the things we really liked about Jose is both JSON Web Signature and the JSON Web Encryption, they all have a signature to verify that it has not been modified. That's a really big deal for us. Making sure that someone can't intercept the message between Citibank and ourselves and go and change the message so that someone can authenticate. We did some really crazy stuff to make that happen. Jose made that super, super easy. Talked about Libit already, so we use JSON Web Algorithm to standardize the format of expressing the encryption and signatures, and you get the ENC and the ALG keys inside of the header, and that's where that comes from, and you'll see that in just a minute. And JSON Web Key, which has kind of solved a real problem for us, like we have a serious problem with key rotation, and so it provides a way of expressing which key was used for this packet, and every packet can be different, so you have a key. And the JSON Web Key information is stored in the header for the JWS or the JWE, and how we used it is we used it to solve every problem that we had, and we literally solved every problem that we had. So here's an example of a request representation. I hope you can read it. Most of it looks like readable. So this is like, here's a standard request, the only thing that may look a little weird is we've got this, you've seen the authorization header. Normally if you're using JWT, you're gonna use a bearer token, so you would have authorization colon bearer space and then your bearer token. We didn't wanna confuse people because we are not providing a bearer token, we're using a JWT, but it's not as a bearer token. So we gave it our own authentication format, which is also helpful for us in identifying what it is, so if we ever change the version, then if we're doing it differently, it can be IV JWT2, or however you wanna do that. And then you see that it's got the three segments, it's very short, it's normally much longer than that, but it wouldn't fit on the screen. So you have three segments that are separated by periods, and then the data is your encrypted data that has five segments separated by periods, which again, is really shortened. And, oh good, it is readable. And so you have your JW header, JWT header with your key ID, which identifies which key we had used. If you know this stuff at all, you'll know that that's an MD5 fingerprint of an RSA key. What algorithm we used for the signature, which is RSA 256, with a shot 256, and it's the type and the content type as a JSON web token. And so for key rotation, that key ID, we provide in the request and the response. And for, if we're receiving encrypted data, you're going to give us the key that you used, our public key, and for us to know which one you used, you're giving us the ID. If we sign the request coming to you, we told you that we signed it with this key. If you don't have it yet, we give you an API endpoint to go get it. So now we can change out keys on systems that are high volume that want to cache the key. It's super important that you're not hitting our key, getting our public key for every single request when you're doing 10,000 requests a minute. That's a lot of wasted time. That's a lot of horsepower going out, making requests for something that you should already have. But it was difficult to do that because if we changed our key, when you cached it, then it can just destroy the world. So now you can just store the key forever because you know that as long as I get, I'm getting the key ID back and I can store in my key value store, I can store the key along with this ID so I can determine if I have it or not. And if I don't, I can go get it when I need to go get it and I can share that value amongst machines. So that was a, it was actually a huge performance increase when we started using JSON WebKey because you don't have to make a call like that every single time you call our system. And you can also get the current public key which gives you an ID and the PEM format of your RSA public key. So that's how we implemented key rotation using JWT. We'd already had the ability to go get our current public key but like I said, there was no way to identify it, there was no way to know if you had it already. Our solution on the version one was send a request and we'll pass along the hash of the key and it's the same when we won't give you any data back so we send less data but you're still having to make a request every single time to see if there's a new key. So now when you make the request, you tell us, hi, I use this key to make the request and if that request hasn't been completely shut down, you can have multiple keys at one time but eventually they will be disabled for security reasons. So if you send us a bad one, we'll tell you that it was an invalid credential but during the time when we're rotating keys, you're not gonna have downtime and you're not gonna have to worry about having the wrong key cached. And so again, the way that we do that is we have the key ID and then we have the URL for the public key. The Korean system is easy to make out of here, I apologize. So request authorization, we use it to solve that problem. So we do something a little bit different with a web token is we do a single use web token. Web tokens are normally you're going to go to a federated authority. If you're using JWT, using something like OAuth2 or OpenID Connect, you go to a federation that says, hi, I'm the issuer of credentials and I'm issuing a credential for this person or for this entity or this application and it's gonna last for however long. Ours are single use because we want to pass those credentials every single time because we are the authorization service and we use RSA key signature and we also have hierarchical ACLs on if I wanna use my organization credentials, I don't wanna have to deal with the fact that I have another two levels. I just wanna use one set of credentials to deal with my 100 applications which is actually really popular if you have a single sign-on system. You have the ability to create and remove all of these other people that are using your single sign-on system, create organizations, a second level inside of our system for mapping to your system and you may not wanna have to manage all those credentials, you just want one set of credentials. And we use the token ID as a nonce and we specifically use that nonce as replay attack and making sure there's a man in the middle awareness. So when you send us the token ID and the request, we're gonna resend it back to you so that you know that, oh yes, this is the response for my request as opposed to somebody sending you a pre-generated response or sending an old response and making it work. And then another big thing is the private claims in the request. So the private request claims are we add the method, HTTP method and the path and a hash of the body and the algorithm that we use to hash the body so that we know which one it is and query parameters. Now the launch key API doesn't use query parameters but that was added in for the rest of the organizations that have query parameters. And so our JWT is not terribly readable, don't worry about so much, we'll go through each piece real quick. But it's fairly large, we use every single thing that you can use inside of a JWT and we add some. So hierarchical credentials is we have issuer, subject and audience. So in this particular example, you have a directory which is basically if you have an authenticator, your authenticator has a directory of users. So you have a directory and so that is your issuer and it's making an issuer based on a service that someone's trying to access. And so we provide, we have UUIDs and basically we've come up with a methodology where we can determine what type of entity is making the request, how to identify that which is the kind of like the three letter code and then a UUID. And then the audience is LKA which is the launch key API so we know if you're saying it's the wrong place we can just tell you that you're saying it's the wrong place. Time stamp and duration, so the duration that we have is five seconds and our response is we allow up to five minutes on the request so that we can have for larger windows. But the thing that we do is we will hash the JWT and store it until it expires to make sure that you can't replay that same token ever again because between the JTI and the expiration there's uniqueness amongst that. Every request you make, you may make a request at the same time but you're gonna have a different JTI. And then because you're setting that we can just very quickly just hash the JWT and we use that for replay prevention and it will exist until the request is no longer valid. So when you have your expiration and your JWT we'll hash it until then because at that point we don't need the hash anymore because the request is no longer valid. So that has really reduced the amount of information we have for our replay prevention because your request is only valid for a very short period of time so we've managed to really, really slim that down. And again we have the nonce for the JTI as the nonce and you'll see in the response it comes back. And a nonce you can give us whatever you want you just better not be the same thing twice because you'll have a problem or at least not for five minutes. And then we have request validation and this is one of the big things that we did with this is the request validation is we created a sub section called request and that's where we put the method, the path, the function used to the hash function used and the hash. So you'll see that the top is the first part of the request. So we know that it's a post request and the location is service v3 auths, the path. And so we have represented that inside of the JWT and that's how we verify that someone didn't doesn't go and change a post into a delete. Our old API wasn't restful because we didn't want someone to be able to turn a post into a delete. So delete was under a different path so you couldn't just take the same request and change the endpoint and do something terrible. Made it secure, it solved the problem but as someone trying to implement that it makes no sense to me at all that I should have to go to service v3 auth slash delete and post to that to delete something. Not very restful. So being able to handle that inside of this request claim removed all of that weirdness that we had to do to prevent that from happening. Response authorization. So one of the things we've never done before is we'd never actually given you the opportunity as a user except for one small little piece to verify that the entire response hasn't been hijacked in the middle. Now the pieces that we did verify and encrypt were the things that would allow you to hijack a session or to impersonate a user or to make a service think that a user had responded in a particular way. So again, no one was ever able to actually log in as a different user or hijack an account or do a man in the middle attack that worked but to do that again we had to just make things really weird and it was really unwieldy as an implementer to try and figure out. So what we changed to, and this is a little weird because you never see a JWT user, at least I've never seen a JWT user in response. Okay, so we actually have a JWT in the response instead of just going with a JSON web signature because we wanted to add a bunch of custom claims and we also wanted to determine what who the issuer was, who the audience is, our hierarchical stuff on the response, we wanted you to at least be able to know what who's responding and what they're responding about. So it had more state and it made a little more sense to us. Although, explaining it to people, it gets a little weird for them because they're like, well, it's a JWT user for request, that's a bear token and we don't use it like a bear token. And like I said, we're trying to utilize some of the existing stuff because now I don't have to make this thing to do this crazy stuff to verify that things are the way I want them to be, that the request isn't too old, that it's a unique identifier, I can just use the existing Jose libraries and they just handle it for me. So again, we do the signature, we put it in a custom token coming back and we also use it that same header when we're sending things for server-send events so that we don't, some people who are implementing don't get caught with the off header because they might have off on their site and bad things might happen if we pass them an off token. Again, the hierarchical credentials, the token ID is not as echoed and we have private claims for the response. And the private response claims, we didn't do everything, if you've ever used, so before we did JWT, we did something that a lot of people do, they go find successful APIs and how are they doing it and who is secure and what are they doing? And some of the older APIs that I worked on, Amazon's the one, right? So you go take like, well, what is Amazon doing? And Amazon goes through and they have this little, one header that tells you all of the headers that they're signing and then they have another header where you actually have the signing and they have to be in a particular order and it's just kind of, it's very secure, but again, harder to implement. So we decided that we wanted to do it this way in the JWT and we identified for our particular API and you could certainly use the same things, less or more, add what you want. These are the things in the response that were important to us because what we don't want to have happen is someone to be able to impersonate a response. So status code's a big one. I don't want someone to be able to return a 400 invalid request and make you think there's something wrong with your API when there's nothing wrong with your request is that someone's trying to prevent you from being able to log in. A cash control header, I don't want someone to do a denial of service on us by being able to change my cash control header and telling you never to cash it or telling you to cash it for an hour when you shouldn't be. The location header for redirects, they can't send you to somewhere we don't want you to go. And then again, the body hash and the body hash algorithm. And so if you take a look at a standard response, it's got your status, content type is application Jose, letting you know that you're going to get that weird dotted part in your body. Cash control location, which I just put in here for reference, we don't ever actually use it. And then again, we have the JWT. So then you have a response claim that echoes that. So again, we have the hierarchical credentials. The issuer coming back is actually the launch key API. The response is coming back from the launch key API and the subject and the audience. So that I now know who the entity is that should be receiving this. So in the Java world, one thing makes requests because it's going outbound and then something completely different might be getting the actual responses back from our service and events because they don't want those applications receiving incoming, maybe at PHP world we've done the same thing, where you'll have all these applications that it's okay for them to go out, but you have this one application that receives incoming requests. And so when you're doing that, you know that, oh, launch key talked to me and it's giving me a response for this particular audience about this subject. And that's been super helpful for us on that piece. Again, the timestamp of the duration is that, hey, if it's more than five seconds old, this is bad, someone's trying to do a replay. A nonce, echoed back to you. So if you generate the nonce, you make the request, you get a response back and they don't match, you have an attack ongoing. That was one of my favorite parts of the implementation is we wanted to try and figure out how to do that and then we realized that, oh, there's this JTI thing that nobody actually really uses, but it's super helpful, so we decided to use that for it. And then the validation. So in your response, right, this is kind of a standard response header. It's not the whole thing, but that entire response header and the response body, which I did include because it's too big, is completely validated and represented inside the JWT. So the same thing we did with the request, we did again with the response and so we have much better. And we encrypted data with JWE. Again, we got that JWK, the web key for giving you key rotation. We get the combination of RSA and AES encryption, so random keys and IVs for AES, super, for doing large pieces of data and RSA to make sure it's super secure. Algorithms and modes are always the same from the request to the response. That's one of the things that we do is when you send us a view encrypt data and you say I'm using AES 256 CBC, we return it back in AES 256 CBC because that's what you wanted. But we do allow a range. So we allow 256 to 512. So most users, 256 is good enough for them, but some people say I have to have 512. So if you wanna get like FIPS 4, you might want 512. Or if you're a bank, you might want 512, right? And we allow them to do that now. We couldn't before. We had to go with the fact that, well, not every language provides anything besides beyond 256. So we're just gonna do 256. Now we have the option for our customers can choose, I want 512. And they can encrypt it 512 and we'll send it back to them encrypted with AES 512. Right, you get the language into that. So the example for a header is very similar to JWT, right? You've got your key ID, except you've got algorithm and you've got ANK. So algorithm is determining what algorithm is used to encrypt the content encryption key. The ANK is the actual encryption protocol. So this one's AES 256 CBC and the signature will be an HMAC with SHA 512. These are all listed. That's super special. And something really cool that we'd never have before is that it actually tells you what is the content type of the stuff that's inside that's encrypted? I mean, that is so cool. Like we, if we might be getting different kinds of data, I can just determine, oh, this is this data and I can get it that way. So if we ever change it so you might be able to use XML, if it's application XML, I know that this one's XML and you need to deal with it that way. So that's something that's a really nice little addition that I'd never seen before in the encryption stuff, which is optional in JWE, but we use it because it's really nice. And so the big conclusion for me, and I mean, I was talking about last night at the speaker dinner, like I'm like really, really psyched about this because it made my life so much better. It made my code so much cleaner. It made my API so much more secure. So much more secure. And we're using standards that are homogenized across, well, they're going to be homogenized across all of our platforms because it wasn't something that was specific. We didn't have to sit down like we did before and come up with something, well, we don't want to over engineer this and come up with something that works for everyone because who has the time to do that? None of us have the time to do this massive grand encryption and signature verification system that's going to work for all of our systems. We've got, you know, we have deadlines to meet, we have to get it done. Fortunately, there's working groups and a ton of people out there using Jose that are doing that for you. So libraries, as far as I know, there's only one full Jose library. So if you want to do the whole gambit, it's Spomkey Labs. But if you want to go, there's also another one, there's actually, I think, two more for JWT, but there's only one that's just JWT that supports basically the full range and the validation of the JTI, and that's it. So he'll be talking about it tomorrow afternoon here. I don't know if this room, but at the conference. Please, please, please, please, please, rate this talk, please rate this talk. And if you want to follow up, if you have any questions, I'd love talking about this stuff, I can do it absolutely forever. But all that said, are there any questions? I thought there might be, yes. What, you said you're using middleware to actually sort of decode the things. Are you using a particular tool there? So we're using just, so using the Jose library, which is handling all of the encryption, decryption, all that type of stuff. So the first thing to do is when it comes in, we just have layered middleware. So the first thing that it does is it goes and it basically, base 64 decodes and URL decodes the pieces to get the header and the JWT. And it determines that, oh, we have, this is a, what type of entity it is, pulls up that entity out of the database and then determines, finds the key that it needs to do the verification on the signature, verifies the signature. So there's actually one piece that pulls out the entities and then it moves the next piece of middleware that goes and validates the signature based on the keys. And the next thing that it does is it verifies that this entity has access to that entity and then another piece of middleware that determines if this particular type of entity can access another type of entity. So we've got a bunch of different layers that go down and then once we validated that this is a valid authorization and a valid signature and a valid request, then we actually go and decrypt and then we just put that data on the request and ship it through. So when it gets the controller, the controller just knows I've got a JSON object, I have a requesting entity and I have a subject entity and I deal with that. So by the time it gets to your controller and your actual code, you know it's a good entity, it should go off and action it, does it also get all the information in terms of basically the payload? Is that already? Yeah, so we attach, we do the database lookup on the entities and so the issuer and the subject, those entities are attached as the issuer entity and the subject entity. So we don't have to go pull it up again. That was one of the big parts of our ability to handle more load is to reduce the number of times we lookup entities. So the middleware does that part of the validation process to get the keys, it actually looks up those entities and stores them in the request and it gets passed on and then we have another piece of middle that validates the actual data that came across in the request because we know the endpoint. Once everything's valid, everything's decrypted, then we can actually do validate the data and then once it gets to the controllers, it knows that it has a good valid request with the proper data that's been properly sanitized and then it just returns a response and then the middleware goes in the reverse order, goes and encrypts it and signs it and then ships it back. Thanks. Can't see, very bright light. I'll ask a question then. Okay. Sorry. Yeah, so taking the full Josie's suite as it is, you would essentially be, am I right in assuming you'd essentially be wrapping your entire communication in its own encryption layer beyond the need of HTTPS as well? Well, we do HTTPS as well. Well, you would, I know, but just saying, generally it's like another envelope of encryption that not necessarily saying it's up to the standard or the same, but it's certainly encrypted. Oh, it's up to the standard of SSL. So SSL is RSA or ECDH, private public key pairs, and it uses AES to encrypt the data. So you're basically using, if you do it using RSA or elliptic curve, encryption, using AES 256 or better, you're basically the same thing you're using inside of SSL. But for us, we know that man in the middle is possible and we try and protect our customers. So if someone, if you're not building your system pinning to our SSL server, pinning to our, making sure that this is who we're supposed to be talking to, you have a man in the middle attack. So we make sure that you could never, never view any of our authorization data. You can never get a username, all these things. So it's, and that you can, you can't just fiddle with response coming back. So it's a, because you can't pre-share a trust, you wouldn't be able to actually guarantee man in the middle being prevented with this. Well, the pre-share of the trust, the fact that so SSL is an open network where you have certificate authorities that you have to trust. So if I go and say, oh hi, yeah, I'm just networking, here's my certificate authority and you go verify against that, but it's not my certificate and it's a different certificate authority. If a certificate authority gets hacked, that's an open network for the trust. When you go to our dashboard and you upload your public key. So the trust is that you went to our dashboard, you upload the public key, nobody knows what those keys are, but you and me. So that's the security. So your client publishes a public key to your API and then that's the, you know, that's what we used to encrypt and verify their signature. It's the one that they sent to us by logging into our system with authorization credentials that are valid. Makes sense, okay. Anyone else? It's really bright. Okay, if there's no more questions, that's it. All right, thank you. And if you have any questions at all or it's a lot to sink in and if you're thinking like, I might think about that, let me go look at it. I'll be here for a while. Go see his talk tomorrow if you're interested in the JWTs because he'll get more in depth than JWT. And yeah, absolutely just come see me anytime and talk to me about it and talk about the stuff. Okay.