Getting Started with Spring Authorization Server

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone are you having a good day are you learning about some exciting new spring features and projects since i can't see you i'll assume that you're all nodding and saying yes welcome back to the intermediate and advanced spring track our next session is about spring authorization server many of our modern production applications require authorization in order to access various features or apis i'm excited to hear about how spring authorization server can help us more easily handle these security concerns please welcome joe granger and steve reisenberg who will give us more information joe and steve i'll turn it over to you right on thanks a lot roy um thanks for coming out to our talk today um this is actually our our first talk on spring authorization server so we're super excited about it we're going to just kick it off with some introductions my name is joe grandia i'm on the spring security team and i've been heavily focused on building out the oauth 2 and open id connect support in spring security over the last four to five years um and steve's presenting with me go ahead steve introduce yourself hey everyone my name's steve reisenberg just really excited to be here i've joined the spring team just about four months ago i've been on spring security with joe and we've been working to just continue to build out the oauth 2 support and spring security and as we're going to present today talk a little bit about spring authorization server it's been a real a real blast and i've enjoyed my time so far on the team i enjoyed working with a lot of awesome community members and really excited for what's coming up so great thanks a lot steve um i'm gonna just start off with a little bit of context um as some of you are probably aware hopefully most of you is uh spring authorization server one production with the 0.2 released um just over a week ago or was it two weeks ago it's like time flies but uh this is a huge milestone because uh we've we embarked on this uh this this uh oauth um rewrite about uh you know about four and a half years ago where the spring security team decided that okay we're we're going to rewrite the oauth story within the spring ecosystem you know as you as you may may be aware the spring security oauth project's been around for about eight or nine years um it is going to be reaching end of life um this coming may of next year may 2022 and uh back then and with version 5 we introduced oauth to client support version 5.1 resource server support it expanded the client support it's been about a year and four months that we've been building out the authorization server support so this 0.2 release is a huge milestone because ultimately it marks um it marks the the the the completion of this rewrite because we have reached feature parity um whoever's using legacy oauth or spring security oauth this is the time to migrate because we have reached feature parity on client resource server and now authorization server so uh feel free to start migrating over um we're going to have some questions a question period afterwards we'll save the questions afterwards and uh yeah let's uh let's jump right into it so i want to just kind of you know i'm going to be really quick on this slide here this is kind of a this is a list of uh specifications that we've implemented so far an authorization server there's a really one thing that i wanted to point out is we're conforming to oauth 2-1 authorization framework it's still in draft mode but this is what we're conforming to and one thing i really wanted to point out is oauth 2-1 omitted a couple of the grants the implicit grant and the the resource owner password grant we will not be providing um uh implementations of that either we're strictly conforming to 2.1 however we're going to remain flexible we've already have extension points for you to be able to um you know provide your own implementation of resource on a password grant if you choose to do so however we highly do not recommend it there's a reason why they were admitted there's a lot of attacks that have been performed on these two grants so um yeah i highly recommend not not to do that we just wanted to point out um because a lot of users have been asking for us to implement that and you know just just to point out again we're going to be conforming to oauth 2-1 we've implemented token revocation token introspection the only access token format that's currently supported is jwt signed gwts as in gws we will be providing opaque token opaque access token support in the coming release or within the next two releases for sure and this is typically where you would use the token introspection um use case to you know inspect an opaque token open id connect support is pretty light right now we've implemented the authorization code grant um however we haven't implemented the user info endpoint it's pretty light but this will be the focus on the next few releases we're going to really start expanding on the openid connect support now if you wanted to get an idea of exactly what has been implemented you could easily go to the repository spring authorization server repository go to the wiki and then here we have the feature list this is a complete feature this will be maintained and updated as we do really as we perform uh issue releases but this is what we've implemented so far as you can see there's some there's some points here we're gonna have some sub points as in you know we haven't implemented the complete openid connect core respect because it's pretty big right so um as we implement we will add points here just to specify exactly what has been implemented to date these are the upcoming features there's actually a lot more but this is these are the key ones that we've kind of outlined so uh so that's that um let's skip on to the next one here so i want to jump into you know this is all about getting started with spring authorization server and and what we really got to get a good handle on grasp grasp on are the core components you know what does it take to configure the default configuration of authorization server what are the required components so i'm going to provide a kind of high level here on the slide but i'm going to jump right into the code because it's going to be a lot more intuitive the registered client this is the client registration information um you know without a without a client the authorization server can't do anything right so this is obviously a required bean as in the registered client repository this is the service interface this provides the crud operations for the domain object registered client or to authorization now this is the end result of an authorization as in an authorization grant flow whether it's client credentials or authorization code so at the end of uh let's say an authorization code grant flow an auth2 authorization gets persisted into the oauth 2 authorization service and it ultimately contains the association of the registered client or the client um that was authorized by the resource owner right that that dual um that dual relationship and then the end result of that is that minimum there's an access token right however if it's an open id connect flow then you're going to have an access token you may have a refresh token if it's configured and you'll have the id token as well stored in the law to authorization there's other things that are stored in an oauth 2 authorization as well then we have the oauth2 authorization consent you know if you're going through an authorization approval phase with the authorization code grant flow this is the consent that's saved so you don't have to reconsent every single time an authorization happens and then we have the jwk source this is the nimbus api that we're leveraging this is the provider of the keys this is where you would configure your keys to sign the jwt the keys that verify the signature of a gmt and so forth provider settings this is where you would you know configure um global settings for the provider for example if you want to customize the authorization endpoint uri and then we have uh the oauth to authorization server configuration and the configure this is the tsl and some static methods in the configuration that allow you to um uh provide a default configuration of an authorization server so let's let's actually just jump right into the code because it's going to be a lot more intuitive looking at the code and i could you know get a little bit more in depth um with uh with some of the domain objects service interfaces let's start off where it all starts right is the registered client okay i mean this is the this is the repository interface pretty pretty you know intuitive right this is ultimately you know typical crud out crud operations right this is where we save a registered client this this might happen in a dynamic client registration flow right which has been implemented if you want to register a client dynamically um and here's find by id this is you know looking up the registered client by the unique identifier or looking it up by the client identifier right so that's pretty self-intuitive and this is obviously a required being without this authorization server can can't do anything right the default implementations are in memory this is really only meant for development testing this should not be used in production this is just to get you up and running quickly we have another implementation jdbc implementation and this could be used for production however there's a lot of different requirements based on um based on your environment you might have a different back backing store that you might want to implement rather than jdbc you might want redis for example um i just wanted to point this out as well is you know we're not going to be providing um any other implementations other than these two because as you can imagine there's a ton of um different types of stores right um and we're i mean spring spring authorization is in the business of application security not data right so it doesn't really make sense to house this these kind of implementations within spring authorization servers so this would be the responsibility of the consuming application and all you really need to do is implement this interface and register it as a bean and that's it right so let's jump into the registered clients and just take a look at a couple of the attributes here i mean obviously we've got the client id this is the unique identifier the id client secret now this there could be a client secret there might not be depending on the client authentication method you know if it's a public client it would be set to none for example the client secret would be no right um but typically you know you definitely want to um you know cater more towards confidential clients because they're more secure i mean but obviously there's use cases for public clients for you know spas and so forth so forth for example those cases you definitely want to be using pixie and pixie you would set over here in your client settings right um here we have is require proof keys by default it's required all right so these are some settings you could set um for the client right now we have you could set require pixie or require authorization consent you know the consent flow but you could also add your own custom settings in here that we're going to be adding a lot more here and then we have token settings as well you know when a token is minted for a client what are the attributes the default attributes of the token you know time to live for the access token are refreshed tokens reused during your refresh flow um what's the time to live for a refresh token what's the algorithm used to sign the id token on an open id connect flow and so forth here we have uh you know what are the supported you could configure the supported client authentication methods does this client support um you know http basic does it also support public like none um we're gonna be adding we're gonna be adding a couple of key client authentication methods in the next release is mutual tls private kjwt and so forth so you could configure the supported client authentication method same thing with the authorization grants which grants can this client perform authorization code client credentials refresh token so forth configure redirect to your eyes for author for redirect-based flows like the authorization code grant what are the scopes this client can request and so forth so that's uh those are some of the key attributes of the registered client now let's jump to the authorization service all right so we'll open up the interface here this is actually not required by default in memory authorization services instantiated obviously in your production environment you're going to want a persisted um persistent backing store same thing with this one we have default implementations are the same in memory jdbc all right typical you know crud we got save remove find by id this one find by token this is used in you know specialized flows if i want to introspect the token or if i want to revoke a token that's what's coming into the request find me the authorization that matches this token so i could revoke it for example right now let's look at the actual uh domain object itself so we got we have a unique identifier we have the association for this authorization so the unique identifier the registered client the principal name so this is ultimately um uh authentication.getname so the unique identifier of the authenticated principle the logged in user right so if i log in as joe this will be my principal name if i authorize client a right and this is what would live in this authorization this is different though for client credentials flow the principal name would be the client id right but there's always that association right and then here we have the authorization grant type what was the flow that was um realized for this authorization and then we have tokens right a mapper tokens as i was mentioning earlier if this was an open id connect flow then this map would consist at a minimum the access token and the id token and potentially the refresh token if it's configured for this particular client and then we have attributes attributes are depending on the flow for the authorization code grant we'll have the authorization request will be stored in there we'll need that when we're doing pixie validation for example um if there's a approval phase then then what will be stored here is what the user um consented to for the client as in the scopes and so forth so that's that's the authorization domain object and then we have we'll jump to the authorization consent service i'm kind of going to skim through this one kind of quickly you know typical crud you know um you know there's consistency as you can see between the three service interfaces that we've that i've been showing you and this is a pretty simplified one right so the association once again the registered client id principal name and then the authorities right so during the consent flow you know your typical um you know consent screen is do you authorize this client to access my your profile information your email right so this would be um you know in here the granted authority would represent those logical names right we want to keep this generic because it could this could either be scopes or it could be claims because what i just mentioned were profile and email email is just you know one claim profile is you know a you know let's say an aggregation of a number of claims right so we want to keep this flexible because you might want to have more finer grained um consensus specific pieces of data right um so that's why it's called authorities there rather than scopes um and then this i'm going to skim through this one really quickly but uh ultimately we're using a nimbuses api gwk source and this is the provider of the keys right ultimately you need to supply the application with the signing key and the verification key whether it's rsa or elliptic curve using java security api and then you transform that to the jw or the nimbuses representation of that here um you know i'm going to share this branch with you guys afterwards so you could easily take a look at the code but basically you're transforming it to um nimbus's representation and then passing into the jwk set really this is going to be standard for for for all you just gotta supply the key wherever that's coming from key store your environment whatever the source is and then provider settings you know i could set you know i could set a few different things here right i could set in i could customize the authorization endpoint i could customize the token endpoint token introspection endpoint and so forth this default this uh i'm setting the issuer here so what this is ultimately doing is it's enabling the provider configuration endpoint so if i jump up to here now you know this is how i would configure the default configuration for authorization server right the absolute defaults ultimately what i'm going to do is i'm going to auto wire hp security and i'm going to call this static method on the oauth 2 authorization server configuration and what this ultimately does is sets up the default configuration and this these are the default endpoints that it sets up so obviously the authorization and point of token endpoint token revocation inspection jwk sent endpoints so the resource server could fetch the keys for verifying and ultimately um you know the client as well could fetch the keys to validate the id token signature because i set the issuer down there it automatically enabled these two endpoints so the standard oauth2 authorization server metadata endpoint and the openid connect provider configuration endpoint and these are the endpoints that clients and resource servers would use to fetch um the provider information to self-configure itself so that's a that's a bit of a whirlwind there but those are really the core the core components you should be familiar with um and the default how to configure spring authorization server defaults now if i jump back into here i'm going to hand this over now to to steve he's gonna you know expand on how can we customize spring authorization server right now all right thanks joe let me share my screen here and so as joe mentioned we're going to focus on customizing this authorization server and i'll just focus on one point which is customizing the authorization endpoint today and so what i have here is that configuration class that joe showed that you can call apply default security to get started if you want to ship with kind of the default setup what i'm going to do though is show that i can actually copy and paste this code and it's totally fine to do that into my own config class and so i've actually prepared that ahead of time here and in addition to copying that code into my own security filter chain being what i've done is i've added some calls to the configure that ships with spring authorization server and so i'm just i'm just showing you that we can call the authorization endpoint here and joe shows that you can customize other things like the token endpoint and so on and here's what you can do with the authorization endpoint so we can do things like set the authorization response handler and so normally the authorization code flow would redirect back to a client and this is how you could customize that and there will be a commit in the repo that we'll share at the end where i show you how to actually switch this out to be a form post and so that's one option and there are a number of other things you can do like set the consent page you can actually override the error response handler that's used and you can even customize the request converter that feeds into the provider but i'm just going to focus on the authentication provider and so i've created my own custom one here and so we jump down and in fact i say custom but i'm actually using the default class that ships with spring authorization server and so it's the oauth 2 authorization code request authentication provider which is quite a mouthful but all i'm doing is creating that with those default service interfaces that joe shared with us the repository the authorization service and the consent service but in addition i'm just going to set one thing and and from here on we'll just focus on this which is the authentication validator resolver and so this allows us to customize a couple of things currently in in main and that is the redirect uri and scope parameters so we could swap out the validation that spring authorization server sets up for us automatically with our own custom one we get a lot of questions for example about what happens when i want to use local host and development and so this is where you might want to start looking to customize that and hopefully you'd say well i'm going to do this in a dev profile i'll set up my own custom redirect uri but in prod we're going to use the one that ships with spring authorization server but however you do that you can provide your own validator and so i've done that here and i have this validator that you might you might think is harmless it's just going to do a regular expression match on the redirect uri but what i'm going to show we're going to have a little bit of fun here and i'm going to role play as an attacker and and we're going to see what happens when we begin to customize some of these things and if we weaken our security posture a little bit thinking that you know it should be fine to be a little bit more flexible than the spec allows for what what can go wrong with that so i've started a couple of applications here and i have this application called honest sso so this single sign-in provider is implemented using spring authorization server and it's it's not attempting to do harm they're one of the good guys they don't they don't have any bad intention however there is this other single sign-on provider or at least it calls itself one and i'm gonna call it evil sso and evil sso unbeknownst to everybody else in this stack here is compromised by an attacker so let's say it was a website that at one point was good and somehow it's become compromised and then i have honest client which we're going to jump to the ui for and this is just a fake oauth client don't copy any of this code and put it in production it's not intended to be useful except for demonstration purposes but you can check out the repo at the end to see this in action and so here's the ui that i have is pretty basic we just have two links we have an honest link that's going to take me to a page where i can launch the open id connect flow for honest sso and i'm not going to show you that because that's going to act pretty much consistently with what you'd expect but instead let's go ahead and switch over to the evil page and see what happens when we launch a flow to that sso that's been compromised and this this attacker i'm going to role play that attacker but this attacker has been watching us and probing our defenses and so this is me kind of experimenting with my hack and seeing if i can get this working so i'm going to click on this link here and what i what i've done is set it up so that we're going to redirect immediately when you launch my evil website and instead of showing you a login page for evil i'm going to show you a login page for honest and all i've done is i've placed my own spoofed redirect uri in the location header in that redirect and then i've swapped out the client id so that it looks like it's honest client instead of evil client and so with that the user may or may not notice that they're actually at honest sso and if they don't notice they might be tempted to log in so we'll see what happens when we do that and i get this consent page and again if i'm a typical user i may or may not notice what's going on i may not notice that this says honest client or maybe i don't even know what that means and so we'll just blindly accept the consent and so what's going to happen here well we're going to get redirected back to the attacker's website instead of going back to the client and that's because we've chosen to really weaken the security of that redirect uri validation and so i've done that and and the attacker just says hey i have your code goodbye and so we've been hacked and our authorization code has actually been leaked over to the attacker's website okay so that's not great obviously so probably that was a pretty naive implementation of our redirect uri validation and so just to show you maybe a trivial but still more secure implementation would use strict equality for that string matching algorithm and this is the recommended starting point if you're going to customize this always do strict matching on that redirect uri and then you can kind of for example maybe you can disable the local host validation when you're in a dev environment but make sure it's on when you're in production okay so that's an attack against our authorization server and if we fix that i'm going to hop over to another commit here that i've prepared that shows another attack and this attack would be when the attacker kind of watches us and sees that we've shored up our defense on the authorization server he's going to turn his attention over to the client and so let's see what happens when he does that so i started up the applications again and i'm going to go back and we're just going to go back to our home page and i'm going to focus on the evil flow again again honest would work as you expect but now what the attacker is going to do is they're going to use the legitimate redirect uri and so i've just placed that here in the location header so instead of redirecting back to my evil website the user that is not paying attention and ends up actually signing in to the wrong single sign-on provider is actually going to go back to the legitimate client but what i've done is i've actually specified a single endpoint that's going to be redirected back to and it's just slash authorized and again you might think that's harmless but in our example we have two single sign-on providers that we've integrated with in this client and so because of that we can't tell as the client which of those two providers redirects back to us so let's see what happens so i'm going to log in here as myself again and i'm just testing my own hack to make sure it's working and what i'm going to do is i'm going to pause the flow in the middle and so before the redirect actually hits the client now in this case i'm cheating it actually has hit the client and i'm just showing you a fake page here but use your imagination that i'm using a tool that kind of intercepts the response and i can kind of play with things here and see whether or not my attack is working and so in this case i can see that the the client thinks that this authorization code belongs to what it's calling evil client which is actually a registration with evil sso and so what the client's going to do is it's just going to hand this authorization code over to the attacker and so if that was the case then again we'd see that we've been hacked or this poor user has been hacked and the authorization code has been stolen so how would the attacker use this so let's see what happens i'm going to jump to yet one more commit and by the way that that attack was called a mix-up attack and you can kind of check out this the best practices document that the oauth community has authored to learn more about that and that's kind of directly where i'm taking this from the next attack though that would build on that is called an authorization code injection attack and so what this is is now that i figured out that i can get an authorization code the attacker wants to know how they can use that let's let me restart my applications one more time here and in this flow we're going to actually figure out a way to get an access token and in this case we're going to try and get an access token associated with a session that we own we being the attacker and that access token in that session is going to belong to a victim and so that's what it means to say authorization code injection so one more time we're going to head over to our client here and actually i need two browsers because i need a victim and an attacker so first i'm going to log in using that same link that the client supports to go over to evil which has been compromised and i'm just going to log in as our poor victim joe here for a second and so joe is going to you know joe probably would read the consent screen he knows knows well enough to do that but let's just pretend that he doesn't like a typical user might not and he just blindly accepts that and again i've paused the flow in the middle and what we're going to do is we're going to actually watch what happens when the client requests an access token from what it thinks is the right provider and that's evil well i have your code says the provider you may leave now in fact the provider has spoofed this as the access token that that that hacked server can actually return whatever it wants because now it has the code and so as the attacker i'm going to hop over and grab that code that i've i've printed out to my console and if i'm quick as the attacker i can now go ahead and inject this into my own session so let's do that so in this case i'm going to log in as the legitimate user and i have my own account with the client and so i'm going to do that i'm logging in as me again i'm just going to skip past the consent screen here and nothing's funny up to this point but here i've intercepted the flow and i'm going to go ahead and put my own or this stolen authorization code into my session and when i do that i can let the rest of the authorization code flow proceed as normal and in this case now my session has an access token but who does this access token belong to it's it doesn't belong to me and i'll just show you by decoding the token here that in fact this access token belongs to joe so i've actually now compromised a session that is on the client and whatever the client can do with joe's access token i can now do and again it probably wouldn't be typical for me to actually see the access token as the attacker but i don't need to i can do whatever this client could do now as joe and just a couple of points that i'll make i was glossing over a few security features that you might might know exist in these flows for example the state parameter or the nonce parameter or another recommendation that the community makes which is that you can actually use pixie to do request forgery protection as well i've glossed over those but let we're just assuming that the attacker is smart enough to figure out how to bypass those protections and even if they can't we can see that if there's one notch in our security chain then we are vulnerable to something and maybe the attacker can use that to kind of bootstrap their attacks and build more and more sophisticated attacks so what's the point here well just briefly in the last amount of time that i have i'll show you that if we don't follow some of the weaker security postures that i set up in that example and we do some of the things that are recommended as best practices for example setting a unique redirect uri for this client so that i know that when this redirect comes back it comes back from the relationship between me the client and the authorization server honest sso that it's coming from that that provider then that will help me avoid this attack and many others and so there's a number of other best practices that you can that you can research and maybe we'll provide a link to that best practice document towards the end or over in the q a section but i'll just show you that this attack would not have proceeded if we had had just that one basic protection in place and so i'm going to go and again i'm going to follow as joe the evil link here and joe as the victim is going to sign in like normal he doesn't know that he's signing into the wrong provider but now the client and the provider in this case spring authorization server have a contract together and they can together participate in this to make sure that we can detect this attack and so the client in this case it really is up to the client to say hey i know that the authorization server valided this validated this redirect uri i can trust it and i can see that this came from evil client not from the legitimate one and so we've stopped the attacker okay so that was a a lot i'm going to turn it back over to joe and joe's going to share with us a little bit about mutual tls and how to customize client authentication and you're muted joe here can we unmute joe okay now okay you're good yeah i lost my uh controls they kind of got lost there steve thanks a lot that was awesome that was awesome um all right so let's uh let's jump to customizing client authentication right this is definitely a very important um a very important piece that an application should be able to customize if you want to add your own custom client authentication that currently um http basic uh client seeker post and public client authentication um is supported with 0.2 um like i mentioned earlier we're definitely going to be expanding it's going to be a major theme the next two releases is um implementing more secure client authentication methods specifically using asymmetric key encryption such as mutual tls and private key jwt those are coming um definitely in the next release next couple of releases the next release will be mutual ts client authentication this is a very very important one the mutual tls client authentication and certificate bound access token specification is of is is definitely a critical very important specification that we will be providing in the next release what this ultimately does is it prevents token replay attacks how does it do that um well when a client authenticates using mutual tls right the authorization server ultimately has the client certificate right and the authorization server could then compute um you know unique identifier for example shot 256 thumbprint of the client certificate and then add that value as a claim in the jwt access token right so it's that access token is bound to that client certificate hence bound to that client so only that client could use that access token however the check still needs to be applied on the resource server side so the resource server side when it authenticates the jwt ensures the signature is valid ensures it's not expired it does this additional check right it also the client also connects with the resource server um using mutual tls the resource server grabs the client certificate computes the thumbprint and then compares right and obviously if it's equal it proceeds with the access request if it's not rejects it right so this is huge because a bearer token a bare access token if if an access token is leaked anybody could use it it's a bearer token the holder of the token could call that same resource server and fetch those resources right but using you know client certificate bound access token this prevents this token replay so let's let's get into it um let's get into that so before i even get into the sample this sample honestly it was pretty complicated there was a lot involved um pki is pretty complicated setting it up um anybody who's um you know uh in operation setting up a you know the pk infrastructure there's a lot involved right so you know i'm going to just provide a high level of what i've set up here i'm not going to get into the details of how i set up these certificates everything's in the repo there's complete instructions and details you could easily look at the details um you know after our talk but i'm just going to give a high level this is what i've set up right so ultimately what i wanted um in this application setup is i wanted all the communication to be mutual tls right so client to the resource sorry client to the authorization server client to the resource server mutual tls also the uh spring the resource server to the authorization server i also want that to be much with tls because the resource server ultimately has to fetch the public keys in order to be able to validate the jwts that are there that are incoming so this is what i wanted to set this is what i want to set up um and i'm using the pki method i could use the self uh self signed certificate method but i decided to go with the pki method this is the hierarchy that i've set up so i have um the spring root ca who basically is acting as a certificate authority this is the root certificate you got cn there as the common name right each certificate has a distinguished name a unique identifier of of the subject of the certificate so here i've given it the name spring root ca and then i got three other client certificates so i got you know i got my oauth client application i got the authorization server application and resource server application those are the common names right so the certificate chain looks exactly like this so when the client um connects with the authorization server using mutual tls the certificate incoming certificate that the authorization server sees is this chain right the root certificate is spring root ca and then obviously the client certificate spring client right so that's that's what i've set up initially let's let's jump into the code and just kind of get into the details of of how this is ultimately set up so um we're going to go back into the the dsl and the authorization server configurer right so this is the root of the dsl we have the client authentication um dsl so this is where you would configure custom client authentication methods what i've configured here is an uh an x519 client certificate authentication converter and the associated provider right so i've technically overridden um the the defaults so this this sample only allows mutual tls does not allow hd basic post or public client so this is pretty tight the sample right as far as your security posture um let's take a look at this how does this implementation look like now as i mentioned you know i'm not going to go into the details of how i set up these key stores or the certificate generated certificates and and the key stores but just to point out quickly um in this repo we have this we have a bunch of commands here key tool commands that basically set everything up so you could easily take a look at this um and ultimately what that generated is my key store files for all my different applications right this is the key store file the p12 file this ultimately contains the private key the x509 certificate and associated associated public key and it also contains the trusted certificate which is spring route ca right so each of the applications trusts spring root ca so we've got to add that as a trusted certificate in there so the ssl handshake um you know ultimately verifies because everyone trusts spring root ca right so when that ssl handshake completes or goes up the chain validation um goes up the chain to validate they both trust spring route ca ssl handshake completes and then um you know eventually it comes into here into this converter and this is this is what we're doing we're trying to extract the client certificate um you know after the ssl handshake is complete the certificate is stored and stored in this well-known attribute on hp servlet request we extract the certificate we're getting the first one because there could be multiple because of the chain the first one is the client certificate we're extracting that um and and that's pretty much it like you know there's some other details here but ultimately we're returning the oauth to client authentication token we're passing the client identifier the the authentication method used and then the credential which is the client certificate so that's pretty pretty simple implementation right and then we'll look at the authentication provider this is ultimately what's called um you know subsequently um casting to the client authentication we get the client id first right and then we're going to look up the registered clients right and then this is the key point that i wanted to you know show here but actually even before i get to this i forgot to show this other p this other configuration that i added here so basically it's the converter the provider and then i also got to configure my client right so i config i changed my initial client from client secret post to tls client that's the only authentication method it supports but then i have this special setting here right and as i mentioned earlier you could add custom settings to client settings and that's what i've done here it's pre by default the prefix is settings.compliant and then i've added this logical name x4 x519 certificate subject dn distinguished names so this is the distinguished name of that client certificate for the oauth 2 client application right commenting sprint client organization spring vmware us right so this is ultimately what would be registered by the client um perform its unique identifier or the subject dn of the client certificate so i'm going to use that here in the provider right so the incoming certificate i receive the incoming certificate over here and then i do the comparison i get the subject dn on the incoming certificate and i compare it to the subject dn that's registered with the client if it passes then i proceed right the ssl handshake happened because i'm here but the extra validation is the comparison of uh the subject dean that's registered with client with the incoming certificate right so that's that's the setup so so there we go so that's literally um you know setting up mutual tls side now how what's the next step as far as binding that certificate to the access token what did i have to do to the configuration okay so i'm going through this flow the client's going through the flow it's calling token endpoint it authenticated using mutual tls it proceeds to let's call it the authorization code grant that's the flow that we're in right so ultimately i'm going to go to the authorization code grant authentication provider we're about to mint the token i want to customize that token right i want to add the client certificate to the token so this is what we would do we would add an oauth to token customizer bean there could be different cut oauth to token customizers depending on the token format currently we only support jwt but in the future or in the next release we're going to support opaque tokens right so the context is going to be different in that case in this case it's jwts so this is the context for the jwt encoding con encoding context right provides relevant information to the specific flow you know um that's currently active right in this case the authorization code grantful so there's going to be different things i could access from here for example the registered client the current authorization um the currently authentic client the authorization code grant parameters and so forth but all i need is i just need the client authentication principle right i want to do a check also i'm only i'm only looking to add this for access tokens i'm not looking to add this into id tokens or refresh tokens so i do that check first then i obtain the client authentication then i'm able to obviously get the x 509 certificate i compute the thumbprint and then i add it into this custom claim all right so now i've added this to the custom claim now ultimately this access token is bound to this client right so i've completed that part right and now the only other part that i need to do is on the resource server side the resource server side needs to look this up and do the same comparison that um that the authorization server does the same comparison right to enforce the sender constrained access token right so let's let's figure that out but even before we even do that let me um i think i got everything started up here let me just double check i'm just going to run through the sample just to show you that everything's working right and then i'm going to add that code that enforces the check and then you'll see that it's gonna fail and then we're gonna introspect it and take a look at the code there so let's just jump in here log in we're gonna do the client credentials grant i'm just gonna open up the debug window so i'm gonna get the token here okay so this is a specific client you know this this client this registered client has has an access token now i'm gonna basically simulate replaying that same token but from another client so i have another client set up with its own certificate and i'm just gonna simulate that client using the token of the other client and ultimately replaying it right now i've replayed it right i've passed that token because ultimately it's just a bearer token right if it was leaked this this malicious client could replay it and get the resources you know so i'm just kind of simulating that there now let's see what happens when we actually enforce the uh the check on the resource server side i'm just gonna check this out and then i'm gonna restart the resource server and then i'm gonna i'm gonna try that again and see what happens actually even before that i'm gonna put well i'll put a breakpoint after let's just let's just refresh this there right so it failed right now let's take a look at the code right like let's look at what did we have to do in a resource server side to enforce this let's go to our resource server config then i'll put a breakpoint but let's look at the configuration first so we got to define a gw decoder right so so the resource server could decode the gwt ultimately um authenticate it as in verify the signature make sure it's not expired but we want to do an additional check right this is some boiler template this is basically setting up the the key store for the resource server um because ultimately the resource server does call the authorization server to be able to to uh do the mutual tls connection but this is the main thing that i wanted to point out right i could add different ought to token validators so i added this one right this x509 client certificate claim validator right i'm gonna run that again and we're gonna just kind of inspect this code and take a look at it so i'll run this okay so we're here now i'm going to compute this thumbprint this is where the check fails right now if i just kind of hopefully everyone could see this this is a thump thump print that it computed and let's look at the x 509 certificate as you can see here the incoming one as you can see here the cn is token replay clients a different client right different client certificate you know this token was assigned to the spring client right so we could see that it's the token replay client client certificate and and the thumbprint here versus the thumbprint and the jwt let's talk about it go to the claims here as you can see i'll do that they're different right that's that's the thumbprint in the jwt this is the thumbprint of the incoming access token as you can see it's different and it basically fails all right so that's that's a pretty simple implementation right i'm extracting a certificate computing it and fails so this pretty much completes um the demo um and what you can do to protect yourself against a token replay attack this is definitely coming in the next release this implementation of mutual tls client authentication certificate bound access tokens so definitely keep an eye out on that um let's jump to [Music] yeah i got five minutes there um so we're we're actually spot on on with time um open id connect core like right now it's pretty light and features um we've implemented the authorization code grant flow user info endpoint is not implemented there is quite a bit in openid connect core and we're going to be expanding on this this will be our focus in the next few releases we're going to be building out the support here we've got a really solid base with the oauth 2.2.1 core now we're going to start building openid connect core features as well um we're gonna we're as i mentioned we're gonna focus on providing you know asymmetric um asymmetric key client authentication um implementations specifically private key jwt mutual tls and this one too resource integrity indicators for oauth 2 this is also a really important specification this ultimately um provides more finer grained control access control on the resource server side so i could say i could do with this implementation i could do the same thing on the resource server side if the authorization server computed the thumbprint of the resource server certificate and added that to the audience claim then the resource server certificate could do that same comparison and ultimately ultimately what it's doing is is i'm only going to accept this access token if it's meant for me this resource server right so once again um just tighter security control so this is going to be a big one as well and that pretty much wraps it up um you know there's a link there to the spring authorization server repo our branches there and uh thank you so much for coming out hope you guys enjoyed it thanks everyone so we're gonna what we're gonna do right now is uh we're gonna jump into the q a room and we hope to see you there and uh we'll answer all your questions all right steve let's jump in there all right thanks guys thanks everyone thank you joe and steve for that great introduction and overview of spring authorization server and steve well welcome again to the spring team we're glad to have you working on the project thanks to our attendees for joining us for this session if you have any questions or feedback please join joe and steve in the qa room as they just discussed uh coming up next in our next next session jen's shouter will presents how to accomplish some of the less obvious features of spring data jdbc we'll see you there
Info
Channel: SpringDeveloper
Views: 6,131
Rating: 4.9712229 out of 5
Keywords: Core Framework, Modern Web, Security
Id: ZIjqDIdFyBw
Channel Id: undefined
Length: 54min 20sec (3260 seconds)
Published: Wed Sep 22 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.