Reactive Spring Security 5.1 by Example

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to reactive Springs security 5:1 by example my name is Rob Lynch and I'm the project lead for spring security and I just want to take a moment to do a little advertising the spring security team is hiring so if you guys like spring security you like application security in spring I encourage you to apply I'm sure you could just google it if you want as well but there's a bitly down at the bottom so even if you say well I don't really know if I can it doesn't hurt to apply go ahead and reach out to us we'd love to hear from you and hope to see you on the team soon so that's enough of our infomercial I want to start talking about our agenda but before we do our agenda I do want to get kind of idea for where you guys are at as an audience so that I can kind of see where I need to focus on so first of all a quick show of hands who here is on spring boot these days good it's usually a no-brainer but you always got a double check all right so who here has used spring security before great show hands awesome who here is using spring web flux okay good show hands as well so who here has done reactive programming before okay great thank you that helps me so today's agenda what we're going to kind of focus on is taking a tour applying spring security to a reactive application and along the way we're going to take a hit at some of the new features in spring security five one and the first thing that we'll do is we'll talk about how to do like a custom user and then we'll talk about we'll talk about how to use the new password support for migrating passwords we'll also talk about how to set up the sample application to use OAuth using the new reactive bits as well and then pending time we will also extract that into spring cloud gateway so that you can put your authorization logic into a gateway rather than your own application alright and as always if you guys have any questions the best time to ask a question is right away so if you have a question go ahead and raise your hand and if I can see your hand I will call on you it is kind of hard to see up here but do keep it up I will try to try to call on you all right so that is the end of my slides one thing I do want to say before before we go any further I do ask at the end of the talk if you could fill out the survey so don't forget to do that and without further ado let's go ahead and take a look at our demo so we have a very simple application here it's kind of my go-to because it's it's a really simple domain to follow it's a messaging application and the application basically just lists out an inbox and then we can also go ahead and delete a message so nothing's super exciting there and then we also have this signup link and in the sign-up link we can basically add a new user so new user and then we'll just give them a new at example.com and type in the password and then you might say well where did that go so our application is actually actually broken up into some micro services so the first first micro service is a user service and we'll see how after we did that actually it's 80 81 so we can see that that new user basically got added into that list so nothing super exciting there but the other thing that we want to pay attention to is there's two users that are already there Rob and Joe and you'll notice that those passwords look like a bit of gibberish right so that's because they're they're encoded and then the new password is just plain text and obviously you wouldn't even expose your passwords on a real rest service if you're doing things securely this is a somewhat for demo purposes so that we can kind of see what's in the database and how we're going to progressively add stronger passwords to our application throughout the other micro service that we have is a is a message service and all it is is kind of displaying our inbox and then you can also view a particular message which we saw in the UI and then the third piece is actually the client so that's our inbox web application which is making the rest calls to these two micro services so nothing nothing super complicated there but it'll give us enough to establish our it'll give us enough to add security to it so now the the real question is can anyone tell me what is insecure about this application okay it's a trick question because there's no security no security so let's see how we can at least step it up and add security to our application we're going to do that first on the inbox application which is just that web application so nothing on our arrest endpoints for now but well gradually add things as we go along so let's take a look and see how we can do that so the first thing that we'll do is we'll go back to here and we're gonna open up our pom file and in here we need to add some dependencies and it's actually just going to be spring security boot starter and then the spring security test jar because you always want to have tests right now for those that are used to spring boot and it's not like a majority of you are you'll notice this is the same starter that we have with nonreactive applications so you might be saying well how does that actually work well the reason is is just similar to how spring web has optional dependencies on reactive bits spring security support is also optional reactive and the way that it figures out that it's reactive is that up here we already have spring boot starter web flux so boot basically see is that you have web flux and you have security and it knows that it must be a reactive web application all make sense okay great so now that we've done that we actually have all that we need for our minimum number of bits to get started so we'll go ahead and restart our application and once it restarts we'll have security applied to it and the other thing that we also want to do is we want to copy this password because by default just as with the nonreactive bits it's going to automatically generate a password for us so let's go ahead and take a look at our application you'll see we get a login page and we can go ahead and type in user and then the password that we provided and we're logged in it was pretty easy next thing we can do is we can just log out there's a log out page you'll notice if you do a get to slash logout it gives the logout form' and that's so that it can provide the cross-site request forgery token who's you're familiar with cross-site request forgery good show of hands okay well we'll skip that if you're not familiar with it you could just google it but it's a type of attack that you want to protect against spring security does it out-of-the-box for you so we'll go ahead and log out and now we've been signed out now the other thing that we have actually out-of-the-box is if I do it through a console here if I do it through this console I get a 401 so you'll notice this is very obviously different than what happened when I did it through the web browser I did a redirect to the login page when I wasn't authenticated and the reason that that is happening is because spring security by default will do basic auth and form login and it determines that using content negotiation so if this client explicitly said I do text HTML not just star slash star it would actually do the redirect now obviously that means that we could just do a basic auth and then we get our page back okay so nothing too surprising there but it's nice to know that you can do both basic auth and in do a form based login in the same application and it happens right out of the box with string security okay so the next thing that you'll probably want to do with your application is you added spring security but you're getting this annoying random generated password and obviously this is not going to be ideal for most users because if you restart or if you have multiple instances you can't really do anything with it so let's take a look and see how we can customize that password first of all so the most the most obvious way if you've done the nonreactive bits and probably the easiest way is to go into your application properties or gamal and you can type in the password here okay so if I just type in the password then we're good to go right nothing too surprising and but it's not too exciting so we're not going to do it that way instead we're gonna go ahead and add a new class so I'll add a new class here and we'll call it security config it doesn't really matter what you call it and we'll go ahead and add our enable web flex security annotation and then we're going to add a password encoder so we'll do we'll do let's not do that one let's do this one so I have some templates to make it go a little faster but here you'll see that I'm basically using a user name and I provide the password and if I start it up with this configuration it would actually blow up and the reason for that is a spring Security's password encoding support is by default using a what's known as the delegating password encoder and it does that because back in the day used to be okay I have a password and I'm going to put it in my database and it's presumed that it's secure because it's in a database and the database has a username password well we realized that that wasn't actually true because they do these SQL injection attacks and do a database dump and the password get exposed to the internet and then they realized also that everyone reused the same username and password so if one site got compromised then you could actually compromised pretty much the entire web so instead we decided as security professionals that we should do a little better protecting our users passwords and we ran those past through a one-way hash and back in the day that used to be md5 and can anyone tell me who thinks md5 is a great idea should we be using md5 yeah you don't want to be using md5 it's no longer secure and then so we decided okay it's not secure because there's collisions it's just not the right algorithm for passwords so we ran it through Shaw and initially Shaw was deemed to be a good idea but we had additional advancements and they realized that because an attacker could just run run the passwords through the hash function and then store them in what's known as a rainbow table they they actually were able to crack these passwords too so rather than doing the work for a specific password that they see and trying to figure out what that is and then doing work again and work again they'd store all that work and then they just look it all up and that all these rainbow tables were available online and so to get past that we decided to add salt and all salt is as random bytes that's combined with the password passed in so the way it worked is you have some random bytes that were stored alongside the password just plain plain anyone could see them and then whenever someone logged in you type in your password and then to validate it they take those random bytes the password that the user typed run it through the hash function and see if that matches what was stored and what that did was it meant now we had the attackers had to do every set of random bytes combined with every password and it just became you know pretty much impossible for them to do these lookup tables because the random bytes were a long large number of bytes now the thing is is in modern day modern day security this is still a bad idea and the reason for that is is because Shaw is too fast it's a cryptographic hash function and it's intentionally fast but with modern day CPUs and even GPUs you can perform on the order of billions of hashes a seconds billions with a B and so that means that you don't need to actually store anything you could just compute it all just compute it right away so the modern approaches to storing passwords are using things like bcrypt or s crypt or argon - these are intentionally pbkdf2 these are all algorithms that are intentionally resource intensive and I say resource intensive very deliberately because it's not only the CPU that's going to be bound but it's also in many cases the memory that's going to be bound so for example s crypt has defenses against using GPU because it takes up more memory than most GPUs can actually use and the other thing that's nice about these functions is their adaptive so it's adaptive one way functions and the reason why it's adaptive is because as the technology increases you can actually add more work a higher work factor to each of these password encoding mechanisms so what is the point of all this why why are we even talking about password encoding well that the point is is that security evolves and in this particular instance more importantly password encoding or storage evolves and as a framework Springs security really can't be changing how it stores passwords all the time as we said earlier it's a one-way function so even when you're using md5 if you did what was best practice 10 years ago now you have this application with all these md5 passwords how do you migrate your users to a newer password mechanism and how do you support that concurrently with your new users so this is what spring security added support for in 5.0 it basically looks for a password prefix and it will delegate to the password encoder and well we'll see that format in just a minute but you'll notice this password doesn't have that prefix it doesn't have it just password so this is going to fail if we started it up but rather than just seeing that we're just going to take my word for it it would fail we're going to see some options that we could do so one thing we could do instead is we could say with default password encoder and then instead of doing with username we just say username so what this is going to do is it's going to say that password that you pass in to me I'm going to actually encode it using the default encoder and so this will actually be stored correctly so this is a slight improvement from what we had before because whatever stored in memory is actually going to be a hashed password in the most modern way you know at that particular time that I got that code ran and so so that's a step up but the problem is obviously the passwords it's hashed into this into the or it's compiled into the source code so it's still this password is still quite vulnerable so what can we do to make this a little bit better well you could just hash it upfront this is really great for demo purposes but in the real world you want to actually hash the password upfront so how can we do that well the easiest way we can do that is we can do spring encode password so who hears familiar with the spring command-line utility that came comes with anyone only a couple hands so if you go to the spring boot documentation will tell you how to install it and it's basically utility for doing things like running running a spring boot application it used to be the way that you'd run like a groovy application the basically the hello world tweet that or the app that fit in a single tweet you could use the spring utility to run that but there's other things into it and since spring spring boot - oh it has this encode password function and what we're gonna do here is we're just gonna go ahead and run that and all I'm doing is sending it to my clipboard so I just grab that remove the newline and then I put it on my clipboard so you don't have to watch me copy paste and then we'll go ahead and add it so now we have this bcrypt encoded password right and now if someone actually decompiled this source code it's you know obviously it's not ideal that they see this hash but this hash is a secure mechanism for storing the password and it takes quite a bit of effort to undo I mean it's it it's very very difficult and one of the questions that we often get is it says bcrypt at the very beginning is that actually secure because it's revealing how the password is being stored is that a good thing is that a bad thing does it does it matter and the answer is in cryptography you often in cryptography it must be secure even if the opponent or the adversary knows what algorithm you used so this is perfectly fine and in fact if we removed bcrypt from the front in there almost anyone that knows anything about password hashing would know that this is B crypt anyways because dollar sign to a dollar sign is kind of a fingerprint for for B crypt it's the version that B crypt is using so there's often telltale signs or fingerprints within within the hash already that most adversaries are already going to know but what does this be crypt do for us why do we actually add it on there well the reason is is we have this delegating password encoder yeah there's delegating password encoder and all it does is it basically looks for that prefix we'll go back to this because it's probably a little easier to see it looks for this prefix that we saw earlier and it says okay if it starts with B crypt then I will validate what the bcrypt password encoder if it starts with md5 I will validate with that if it starts with XYZ I'll I'll validate with XYZ so by default we pre configure a certain number of password encoders but you can always customize this but the difference is is that if you encode with this it's always going to encode with the most modern mechanism at that time but we can still validate passwords that are basically encoded in any of these formats so say you made that right choice ten years ago you can actually add that prefix to to your md5 and then use this delegating password encoder and then encode and bcrypt going forward I'll make sense awesome so we're gonna go ahead and move on from here we've already customized the password and we're gonna go ahead and just see that in action real quick just to make sure we're still working and so all I got to do is I can type in so remember I used Rob at example.com for that and then I typed in the password so it's working as expected now one of the things that we didn't show is that it's actually a little bit broken right now so if I try to delete this we talked about the cross-site request forgery token it's not getting included in the request and in fact there's another thing that's broken too it's this I'm logged in and I see sign up I don't see the logged in user and if we look at our layout so I'm using time leaf here and all it is is just a templating engine if you're not familiar with it but basically what it amounts to is I'm trying to include the current users name so and that's basically the user name so how why is that not working and why is this current user no well and how do I access the currently logged in user I guess more more appropriately so the reason for that is is because we're using reactive bits nah you don't want anything to subscribe to either the token itself or the authentication it's the authentication unless you need to use it so spring security is placing making those available but our application doesn't see it in the model and an easy way to get through that is actually just to do a security controller advice and the name is arbitrary but that annotation controller advice is something specific anyone anyone familiar with controller vice who's here controller vice okay only so this is basically kind of like a filter it's like an aspect in that these models will get populated for every request within spring MVC and you can you can narrow it down if you want and stuff but we're just going to do it for everything and all it's doing is it's saying okay I'm going to resolve the cross-site request forgery token and then if you look at our forms that we have we're just using time leaf and then time leaf will automatically recognize it and add it for you so as long as you're resolving it using this mechanism and the source code is available later on so if you want to see that you'll be able to get it from there and in fact and I can't remember the version but it's coming out shortly time leaf we'll do this for you so that's that's coming very shortly and then similar for the current user time leaf can we'll be able to resolve that for you as well but for now the easiest way is to just resolve it for it so we'll go ahead and start our application again and we'll see that when we after we log in we should be able to see the currently logged in user the signup button will go away and then also when we try to delete something it should just work so we'll go ahead and do Rob so if we you see I at the upper right it says Rob and it gives a logout button and then I'll go ahead and delete this message and it goes away without there so we're able to resolve those pieces and again that support is coming built in to time leaf in the very near future I'm not sure the exact dates though okay so this gets us a lot further along in our application but it still leaves a bit to be desired because if I if I see this login page the login page was very handy because no code had to be written from the user's perspective all we did was add spring security but it doesn't fit with the rest of the application now that I fixed that quirk with the currently logged in user there's no link to the signup page right you'd expect that to be on the login page or any public facing pages so how can we add a custom login page that fits our UI and allows us to sign up new users we're going to take a look at that next so we're gonna open up our security config and in here we're going to add [Music] the most basic configuration so you might say well where did that come from if you don't know what the default configuration is if you didn't do anything this is it but if you need to get it it's actually just on the Javadoc of the enable web flex security annotation so you can just you can just basically copy paste the code that we had from there if you need to know what to do by default all right so this is what's happening by default but because we haven't specified a login page for Spring Security it's going to render that for you so if we actually provide one if we actually provide a login page very much like the the servlet bits then it'll it'll actually try to render that page instead it will redirect to that page now of course we want to make sure that we grant access to it so let's say I login and then we have some CSS so we have to say web jars that's where all our CSS is and then we're also going to say users sign up so these are all the things that we want to make from it all okay so we're just granting access to any user you don't even have to be logged in anyone can see those resources and then they're able to do that so we'll go ahead and restart the application and while that's restarting let's take a look and see what our login page looks like I already had that typed up just so that we could move along a little faster the controller is very obvious it's just if it goes to the URL login then do the view login and then the login HTML page is also very simple if you've done standard spring security all it is is a post to slash login we check for air parameter and then we say that invalid username password we also have check out for the logout parameter for a logout success and then we have a username and a password and the those HTTP parameters must be a post to slash login and again you need the cross-site request forgery token in this request but because we're using time leaf and we did our controller advice time leaf will automatically see that and populate it for us so we don't have to do anything additional there so now let's go ahead and go up to here and it appears that it didn't start so we'll go ahead and check that out real quick let's see here my dress what's that oh yes thank you thank you yep so what I'm trying to teach you here is that it's very important that if you if you do it in the wrong order things are going to break and what spring security is trying to tell us here is that that basically you cannot each of these paths are a consorted in order and so because earlier it was like this path mattress was second yeah it was saying okay the first the first thing I was checking is is it any exchange so every match everything and then authenticated right so if it's any exchange then you must be authenticated well that means that no additional rules are actually going to apply right and so that basically this error message is saying you can't have match anything and then another rule because that other role never get matched it's only the first rule that gets applied so instead what we need to do is we need to move it up and then since we moved it up it will now consider the login web jars users sign up from it all first and then any exchange makes sense all right so we'll go ahead and restart that again thank you very much there Josh go ahead and start that up and we get our login page and now you'll see it looks a lot more like the rest of our application and if we inspect it let's inspect this so yeah in here you'll see it might be hard to see there so we'll just do this G and it probably should have made this think this a little bigger so what it did was it automatically added that it automatically added that cross-site request forgery token in there so you can see basically that that input was automatically added for us even though we didn't code it ourselves and now what we can do is we can go ahead and log in as our user and then log out and if we log out we basically see the logout success if we try to log in and valid information we get our username invalid or user name password a melody okay so now now we have a reasonably good-looking application well I guess you could argue it's not that great looking because I did the UI and I'm pretty terrible at UI but it's at least reasonably consistent right so now you we really want to resolve another big burning issue I have this user in the security config that is different than the users that are in my system that we already looked at so we already looked at these users here it doesn't make sense that I have a separate system for my users and in fact almost all the time you're going to want to have your own way of storing your users in retrieving and validating the users and the reason for that is is because you're probably going to have custom properties so here I have like a first name and a last name on there so maybe instead of saying hello username you want to say first name last name or just first name whatever you might need to access that identifier and you might say well why aren't these properties actually on spring security in the first place shouldn't spring security just have these and the answer is well spring security is only interested in its own domain right it makes no sense for us to add an ID on there because spring security doesn't care about the identifier it mate has nothing to do with the authorization logic or authentication that it's trying to perform and what's more is people might not necessarily agree on these additional properties for example someone might want first last name someone might want full name and someone else might want a address and someone else might want someone else might want a list of cars that the user owns and so you can see how this would get very out of blown out of proportion and you know we can't just add all these properties but it makes sense for your domain to have your domain specific properties on there so let's see how we can actually use a custom user detail service reactive user details service with our existing domaine so we're going to go into here and we're going to add a new class and we'll call this one service reactive user details service and we're gonna make it a component so it gets picked up automatically and then we want to make sure we implement reactive oops that's the wrong one reactive reactive user detail service and then we're gonna go ahead and implement that method so all it is is given a user name give me a user details and that user details is stuff like what roles does that user have what does a password look like for that user etc alright so this is pretty easy for us to implement we actually already have in our application a way of accessing our users we saw that because in our in our application we're seeing the messages and the user information within the messages so we already have a way of doing that so let's leverage that API and most likely you will probably have that as well so it doesn't really matter how you do it but ours is going to be a we call it a user service and then we're going to go ahead and add a constructor so obviously that gets auto wired by spring automatically because of the single constructor there and then the next thing that we're gonna do is we're gonna say okay this tzer's defined by email and we're going to use a user name so our user names are going to be our email address a pretty common pattern and then what we need to do is we want to map it let me bring that up to the top so you guys can see then we're going to go ahead and map that to a custom user alright and so the first step is we need to create our our custom user and then we also need to create a custom structure so this custom user we want it to actually extend we wanted to extend user and that's our own domain model right so it is a user and then we also want it to implement user details okay so now that we've done that we can go ahead and auto generate those methods and our our current user already has a constructor that takes in an existing user so that basically copies all of our domain logic into into this one but then we also need to implement user details now you could provide any sort of mapping you want for these other properties maybe you have them in a database maybe they're part of the results of your existing user maybe they're in a separate service it doesn't really matter but provide some sort of mapping logic and like any like any good demo I've come up with the most complicated way to map that I have a constant here of role user but obviously you can do however you need to so then we're going to do get user name we're gonna just say get email right and then all these other ones are flags to determine if this is a if the account is expired or if if the password is locked or anything like that so we're just going to do we're going to just replace all of those with true alright so that is our object now the thing that's interesting about this is again it's a user and a user details so when we're returning it by from this method we could refer to it as user because it is a user and spring security can refer to it as user details that means that we get the best of both worlds spring security has a user details that it can make authorization decisions based on and we can refer to it as a user object so that we can refer to our custom properties and yet we are not tied into spring Security's domain domain everywhere in our application anytime we make a query or any time we're trying to display any information it's just our own domain model nothing to do a spring security whatsoever make sense all right awesome so now at this point we want to actually take advantage of this this custom user that we've created so let's go ahead and update our security controller advice so we said that that principle that we're returning from that method is both a user details and it is also our own custom user so let's go ahead and add a way to access it so this authentication principle mechanism is basically getting from the security context there's a spring security has its own context as this context and in there it has an authentication and that authentication has a principle right and we just said the principle type is going to actually be what we were returning so authentication principle is actually is referring to that type so that means that we can change this type to just be a user and then we need to change the return type to match that oops so now we can change the return type to match that so now this type actually has all our custom properties on it and nothing else even though it is the user details and a user were and we're insulated from that we don't care that it's user details we only see that our properties so in our layout now we can say and for the current user we can just change this to be instead of name we can just say first name so we can access that so now when we login we should see the users first name instead their email address we're accessing custom properties for the currently logged in user so now that we've done that we'll go ahead and restart our application well that's restarting one good quick drink any questions well that's restarting okay and this is another thing that you have to do if you have added a new user detail service you have to remove the old one so we need to remove this old one because otherwise spring security doesn't know which one to use and it started so we'll go ahead and start that up and now we should also be able to expect to not only login with Rob and see oh yeah actually this is another this is another thing that we want to make sure that we do this is the error message that we were talking about earlier so it's saying there's no password encoder map for the ID null and the reason for that is if you remember in our users the users that we're leveraging note don't start with that prefix right so the the easiest way to do that if you're in a old system is to just change your beam here expose a actual beam to be password and then we're gonna return new standard password encoder and it's it's you'll see it's deprecated and the reason why it's deprecated it'll say in the Javadoc is yeah we aren't gonna remove this anytime soon but you shouldn't be using it so it's kind of a flag to you to say hey don't don't really use this because it's not secure but we understand that you're kind of stuck in this situation so we're not gonna get rid of it anytime soon just don't use it in the future and try to get away from it so now that we've done that we should be able to log in with our users wrong okay with Rob logged in no problem and you'll see up in the upper right hand corner we are Rob and then if we log in again we can log in with Joe and we're logged in with both users and we see Joe at the top alright so now we're able to refer to custom properties were insulated from spring security because we're using our own domain object and we're accessing our own users in our system but it still leaves us with a little bit to be desired because our our passwords are not stored in a secure mechanism so let's see how we can update to support that all right so the very first thing we should do is we need to update to use the delegating password encoder so you can say password there's this password encoder factories and it creates a default instance of that so it has all the standard mappings this is explicitly providing a beam that is what spring security uses by default so if you're not using password encoders anywhere else you don't even need to declare this beam but we're gonna leverage it later on so we're gonna actually place it there so now that we've done that we need to actually do a data migration for our users so we have we have this initializer here and so what I'm using is I'm using embedded and and so this is how I populate the data each time obviously you won't have the exact same logic here but the goal is really to prefix all the existing paths with sha-256 surrounded by curly braces so you can imagine in your own system it's pretty easy to iterate through all your users and prefix with sha-256 it'll vary by system obviously but that that's how we're gonna end up doing it so now we can go ahead and restart our user application and then we're going to go ahead and restart our inbox and while that's going we're going to take a look at our users again and you can see now our data migration worked it's it's prefix with sha-256 right so now if we go ahead and try to log in it works just fine with the default password and the the default password encoder so what does this buy us well let's see what happens if we add that password encoder to where we're signing up so we're going to go ahead and go back to our inbox application and in there we're going to go to the user controller and in here we're going to add a new variable password encoder and I think I might be in the wrong oh yeah that's in the user1 apologies that's their own one has to be there's a user controller for our rest service but there's also one for our inbox so the classpath doesn't that have spring security on it yet for our service so we'll do password encoder and then we add the constructor parameter now the other thing that we're gonna do here is we need to say whenever the user signs up we want to do on success I'll say you your dot set password user duck password and so all we're doing is saying whenever the user signs up and code the password using our password encoder and then we're also going to say subscribe on and I'll explain this in just a second subscribe on in reactive is basically a way of saying which thread to run on and this is important in this case because password encoding happens to be a blocking operation in the sense that we talked about how it's CPU intensive it's recommended that it takes about one about half a second to one second to encode your passwords and validate passwords so if you're using a reactive application which everyone in here said that you know pretty much everyone said they've been doing reactive programming you're gonna be blocking the main thread so you can't do that so that means that you actually have to offload how you validate the password on to a separate thread pool and this is no exception because it's encoding the password it takes a lot of CPU we have to delegate to a separate thread pool otherwise we're blocking the dispatcher thread all right so that's the easiest way to do it it's pretty simple and then now if we restart our inbox application we should be able to sign up a new user and so we excite up that new user and now we'll just go ahead and take a look at the list of users and you see that we have have not actually added it yet not actually in code I'm sorry oh thank you you got it you guys are you guys are passing the test I appreciate that encoder encode so we'll go ahead and we have to restart two applications because otherwise we'll have two two of the new users in there yes yeah all this source code is going to be available online so if you're wanting the source code it's gonna be it's actually already in github so and I'll make sure you guys can find it alright so we'll go ahead and restart the inbox application and obviously it's not going to be there anymore so we have to go through that flow one more time and well do you so now we have signed up and you see now our old users started start with sha-256 and the new user starts with bcrypt okay so now new users are able to use the new safer mechanism and old users are still stuck with that because remember it's one way we can't undo it so what we can do now is we can say new at example.com and we can log in as them all right so it's pretty nice that we're able to do that for our new users but what about our old users now this is a new feature in spring security 5-1 and the way that we can do that is we've added a new a new API so we're gonna go ahead and take a look at that all we have to do for our service that we created earlier is add one more method and implement a new implement a new interface so it's called reactive user details password service and as you can imagine it's just for updating the password and we can implement that any way that you need to based upon your you know your system but we're going to say users find by email just like we're doing earlier get the user name and then we're going to map that to messa a method called this create and in here we're gonna return mono user details and this create method needs to now basically given our user it needs to be able to create create the create the create actually we want to do this first I apologize first we want to say do onsuccess we want to say there we go do on success so this is our own domain type user dot set password and then new password that's already encoded for us so we don't need to do anything extra there and then after that we want to map that to we want to flat map that to this users safe so that way it's safe for next time and then the next thing that we need to do is we need to it a wild key there apparently the next thing we want to do is given given the user that we just save we can reuse our custom user new and so this is very similar to what we saw with the mapping of find by username we're just mapping it to that same custom user after we save it okay and then if we restart our inbox application now if I log in as Rob it should update the password if I log in as Joe it should update his password so we'll go ahead and log in as Rob first and now if we look at the results of our users you'll see that Rob starts it with bcrypt and we already saw that we can log in with bcrypt because we did that with the new user if I logged in with Jo it would also update now the other thing that's important is it won't update a user that's already up-to-date it already knows if you're using bcrypt it doesn't need to update again and that's important because as we said it takes half a second to a second for each for the validation and then another half a second to a second for the upgrade so this is a nice way to do it and now what you could also do is you could say hey users please go ahead and change your password because we're making security improvements or however your marketing wants to spend that and that's good because if you're storing it at md5 and someone got ahold of that password is probably not secure anymore so they probably want to actually change the value of their password as well but this is more of a business decision versus something that spring security can delegate to you but you could send out an email and say hey please change your password because of XYZ and then that would not only migrate their passwords but it also also encouraged they're also in stored it in a more secure mechanism okay any questions with that all right yes please so the question was what was the password stored in before so if you look at Joe's password Joe's password is an existing user it's stored in sha-256 so what we did was we validated it was valid when they typed in their username password and once they validate once I validate it I had the original password and I was able to hash it in the new mechanism and then store it because there's no way to actually undo it but if they typed it and we validated it we know that it's valid and we can use that to store it again does it make sense awesome yes please so the question is is if you if you have a whole bunch of empty five passwords and you want to trigger them to basically update their passwords is there a way to redirect them to the update password page and and the way that you would do that is you would you would I'm trying to think of the best way to go about that most likely I would say you'd probably want to do it as a filter because you want to make sure it happens all the time you don't want to just let them bypass it again it's probably more of a business decision but you could do like a non authentication success you know do some sort of logic because there's a success Handler and then basically if if I need to do something redirect to that page as well so if you want it all the time you'd have to do it as a filter because otherwise they could you know bounce around if you only want to try to get them to change it and not force them then you just do a success handler makes sense cool all right yes please yes so the question is these algorithms are intentionally resource intensive so how do you deal with your SLA s and there that's kind of why you have this balance between security and and practicality you know ideally you would have it take 20 seconds you know because that's even more secure but it's just not practical and it also leads to the fact that if you're you storing your passwords in a valid manner HTTP basic is not a real option because every request is going to be at least half a second because that's how long it takes to validate the password so what you really need to do is exchange credentials for a short long term credentials for a short term credential and this is not unique to reactive applications it's across the board because that half a second happens regardless if you're a reactive or non reactive so the key is to exchange for a long term credential for a short term credential like a session identifier or an OAuth token or insert XYZ does that make sense right yep yeah and so the comment was is the other thing to notice is the one user only has to do half a second delay whereas the attacker has to wait for every password they're trying to to decipher and remember also it's not it's one way so the only reason why we can do it in half a second it's because we have the password and we could say yes or no if you don't have the password this takes much much much much longer right okay good comment thank you alright we're gonna go ahead and try to move along here because we still have the most interesting bits to discuss I'm gonna pick up the pace a little bit by cheating see if I can spell master we will get much further in life spelling was never my strong suit so we're going to go ahead and jump to client credentials actually I am going to do something even crazier and not quite that far actually we want to cover quite a bit of material so we're gonna just do jump ahead and I'll go over the code versus watching us type it and now the other thing that I need to do is I need to go through here and restart all of our all of the apps that we have so we'll start with the user one and then we'll do the message one I'll do the inbox one then we're gonna start restart the Gateway - all right and we're gonna presume that all of the start just fine that's usually a first make mistake of any anything any presentation is presuming anything but what I'd like to do is show you how we can add a resource server support to our application and then use the web client to interact with those resource servers and then see how we can do single sign-on with Open ID Connect and then after that see how we can extract out our resource server logic into the spring cloud gateway so lots of stuff to cover obviously but I think it will be worth our time so the very first thing that we need to do is go to our application here and if you're doing any sort of resource server stuff you want to make sure that you add the right dependencies so here you'll see I have the resource server and no auth to Jose so that's the way that we can do tokens and that's all you need it in terms of dependencies and then in terms of setup what you need to do is you want to add a application amyl for the user service so in here I have this issuer URI and that URI is basically the way that we look up the public keys so if you're not familiar with the issue or a URI there's a convention that allows you to look up the JW KS URI which exposes the public keys that you're validating against it's nothing surprising if you've done OS support or before but that's all you need to do in terms of adding resource server support to the application spring boot will recognize that and then configure configure it for you automatically so then the next aspect is is we want to see how we leverage that so if we're leveraging that in our inbox now the first thing we need to do is configure a client registration in the client registration it's just a way of saying this is something a client that has a key and a secret and it points to this endpoint so you can see here I have one provider and that provider is pointing to the same issuer uri same metadata that it's discovering and then we have two different registrations here one's a key cloak - client and one of them is just key cloak and the key cloak - client one is using client credentials and then the other one is using the default which happens to be authorization code and we'll use that for logging into our application and also getting access tokens so the next aspect is we need to make sure since we've provided explicit security in this in this application we needed to state two spring security hey I want to opt into OAuth 2 client I want to opt into OAuth 2 login so that's that's all we're doing here and spring boot is creating some beams that that OAuth 2 client and OAuth 2 login are leveraging from those properties okay so now that we've done that the other aspect that we really want to do is we want to be able to pass along our we want to pass along our credentials so there's a couple pieces that will do here we'll create what's known as a exchange filter function and it's the OAuth support version of it and this is basically a way of saying with the web client which is a reactive way of doing rest template with the web client I want to automatically include an authorization token and if not it well you don't have to automatically but we've explicitly opted in to automatic there or you can explicitly provide it and if it's expired will automatically refresh it so you pass pass it along tell it and then spring security will automatically refresh it if it's expired and it'll do all the logic that you need for that it'll make a little more sense when we take a look at how to lever so we're going to take a look at the reactive user detail service so this reactive user detail service now has a up that's not what we wanted we wanted the web web client user service so this is how we're interacting with the user API right and we just inject the web client like we normally would but then we're doing this attributes key cloak client credentials what is that well all it's doing is it has a static method that says client registration ID equals key client so that means we want to use that registration information we saw here Piko client to make our request so Spring Security will see oh it's got this u issuer URI so I know how to get the access token using client credentials of a key and a secret provided right there make sense so all it does is say if the access token exists then I'll use it otherwise I'm gonna look it up using that information and it does that automatically if it's expired it'll go ahead and refresh it okay so that's explicit usage but you can also do implicit usage so going back to what we saw earlier in our application code we also can say set default client registration ID so for our other endpoint because it we didn't say what sort of access token we wanted to use we will automatically use that so in our message endpoint we don't have anything and nothing changed in here it's it's just the same web client usage we didn't say any attributes or anything like that spring security is just going to do that out of the box you don't even have to do anything special there all right and then the last piece to all this is in our login page we want to make sure that we have a way to trigger a login because we can log in via form login now or we can do a single sign-on and the single sign-on is just a convention of OAuth 2 authorization key cloak so key cloak is that identifier that we saw in the application UML earlier as well alright so now that we've done that I can't recall if we restarted thing or not but I think we did yep so now that we did that we can actually just go ahead and see that in action so I go ahead and redirect and now I'm redirected to any open ID provider will work key click just works very nicely locally so I can just do that and then I'll log in with Rob and then I'll type in a password and I'm single signed in and the other thing is is it's hitting these these endpoints here so if I hit users I'm not authorized because that's our end point so you can see that it's automatically getting that access token behind the scenes and we didn't have to do anything and it's doing it using something like this so all I did was I I made the call to get the access token using client credentials and I exported it to a variable and then we'll go ahead and use that and now I'm able to get the at the endpoint so you can see that the users own point is now using it and so is the message endpoint we're just providing the access code version of that token in that endpoint does that all make sense to everyone all right great all right so the last piece that would really be nice is if we didn't need to if we didn't need to do the logic in every resource server maybe maybe we don't have a hard requirement of having security right at the right at the service itself maybe we could just use like a gateway so we can just undo the security that we had in there and then leverage the Gateway and I just reset that and so now we're gonna go ahead and restart all our applications and our gateways should be fine already because it didn't really change so now if I access it the users directly I actually get the user without any problem because I removed security from it but what I can do is I can say now all right if I access it through the Gateway the Gateway is basically routing traffic from it to the to the resource server only if it succeeds so you can see this is not succeeding but if I do use a ssin and you have to do bearer of course and and now it now basically it's happening there now the one thing that's interesting is you might need to do some little bit of custom logic in there so for our gateway one of the things that we did was we turn turn information from the axis from the jot token into a header that's passed alone so here you can see it was probably not extremely obvious what we're doing here but we're taking something from one of the claims of the jot and we're injecting it into the header so that header is basically forwarded on to the user service or the message service and the reason for that is is if you beforehand our message service was saying okay the currently logged in user I'm going to use their identifier to figure out what their inboxes but we need that information even though there's no jot you know that we're validating on that side so here you can see if I just say messages let's just skip the authorization because we don't care about that but if I say 8080 a two so if I do that it's gonna be a bad request and the reason is because it's wanting the ID and then I could just pass in the idea of the user I'm sorry Oh users thank you so we're able to see that information so all that gateway is doing is transforming the jot into a header that's relayed on to that endpoint and then you're able to leverage that and how we added resource server support to the Gateway it's just a standard spring reactive application so it's exactly what we saw earlier when we added it to the user endpoints but we're only doing it in one location does that all make sense all right great well with that said we're gonna wrap up and leave a couple minutes for questions if anyone has any additional questions if I don't have time for your question then I'll be glad to answer it afterwards so anyone have any questions yes please so the question is the question is is there any integration with the rest template support and the answer is no the reasoning for it is is because well you can manually include the you can manually include the header in there but it were going forward Spring Framework is really pushing people to move to web client throughout so rest template it I wouldn't consider it deprecated but it's we're really trying not to we're not really adding much new features in that respect and it also doesn't have a lot of support for things that we want and need so there's no way to pass an attribute to it like the old dress template support the only way you could basically communicate the access token was explicitly using you know using the API is that ahead of like here's the header or whatever whereas with with the web client you can say I have this random this random attribute of client registration ID and then the filter the exchange filter function that we registered can use that information to look up the access token that needs to be added perform some logic on it and then basically pass it along so there's lots of pieces missing from rest template good question we have time for one more question yes in the very back but the Hat please oh the bitly link yes yes I'm sure so let's see so let's see here we go there we are alright well thank you very much for your guys's attention and if you guys have any other questions feel free to come up here and ask but I'll need to shut down for the next person thank you very much you
Info
Channel: SpringDeveloper
Views: 21,312
Rating: 4.9210525 out of 5
Keywords: Web Development (Interest), spring, pivotal, Web Application (Industry) Web Application Framework (Software Genre), Java (Programming Language), Spring Framework, Software Developer (Project Role), Java (Software), Weblogic, IBM WebSphere Application Server (Software), IBM WebSphere (Software), WildFly (Software), JBoss (Venture Funded Company), cloud foundry, spring boot, spring cloud
Id: YcAufUtfm44
Channel Id: undefined
Length: 68min 47sec (4127 seconds)
Published: Thu Oct 04 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.