1 00:00:00,490 --> 00:00:03,050 Okay. So we had quite a nice dog and pony show 2 00:00:03,050 --> 00:00:07,080 building out our web facing repository that communicates using hyper media. 3 00:00:07,080 --> 00:00:11,920 I'd like to show off now how we can add a layer of security on top of our API and 4 00:00:11,920 --> 00:00:14,530 make sure that we restrict access to the right people. 5 00:00:15,630 --> 00:00:18,420 Our product manager Hannah has requested that all users 6 00:00:18,420 --> 00:00:20,700 of our API are authenticated. 7 00:00:20,700 --> 00:00:23,560 And remember that means how we identify our users. 8 00:00:23,560 --> 00:00:27,220 Over the next few videos we'll build out some basic security just so 9 00:00:27,220 --> 00:00:29,080 that you can get the gist of things. 10 00:00:29,080 --> 00:00:33,470 So let's do this, let's store who created each review using our API and 11 00:00:33,470 --> 00:00:36,200 we'll further make sure that only administrators and 12 00:00:36,200 --> 00:00:38,810 the actual reviewer can delete reviews. 13 00:00:38,810 --> 00:00:43,520 That's right, right now anyone can delete any review in any course for that matter. 14 00:00:43,520 --> 00:00:46,970 Yikes, we better put some protection in place, but first we need users. 15 00:00:46,970 --> 00:00:47,570 Well, let's do that. 16 00:00:48,750 --> 00:00:51,700 All right, so we're gonna lean pretty heavy on spring security. 17 00:00:51,700 --> 00:00:52,540 Now, if you're looking for 18 00:00:52,540 --> 00:00:55,610 more information on spring security, there's a workshop for that. 19 00:00:55,610 --> 00:00:56,910 Check the Teacher's Notes. 20 00:00:56,910 --> 00:01:00,660 So let's add spring security to our gradle build file. 21 00:01:03,170 --> 00:01:12,921 And what we want in here is compile 'org.springframework.boot:spring-boot-sta- 22 00:01:12,921 --> 00:01:16,045 rter-security'. 23 00:01:18,170 --> 00:01:23,370 All right, so now we need to add a new feature to our app and that's users. 24 00:01:23,370 --> 00:01:25,010 So, what should we do? 25 00:01:25,010 --> 00:01:26,970 That's right, create a new package. 26 00:01:26,970 --> 00:01:32,440 Let's add our newest feature, users. 27 00:01:32,440 --> 00:01:34,424 So it's gonna be user.User. 28 00:01:37,708 --> 00:01:41,860 We're gonna mark this as an @Entity. 29 00:01:41,860 --> 00:01:46,991 We're going to have it extend our BaseEntity and 30 00:01:46,991 --> 00:01:52,720 we're gonna wanna have a first name and a last name. 31 00:01:52,720 --> 00:02:00,270 So, We'll dupe that line, and make this last. 32 00:02:00,270 --> 00:02:04,517 And we're gonna be using this to login, so we're also gonna need a username. 33 00:02:04,517 --> 00:02:11,084 So we'll do, private String username, and since we're gonna use for 34 00:02:11,084 --> 00:02:15,580 authentication, let's add a password field. 35 00:02:20,376 --> 00:02:24,350 Now, remember, we have this exposed on the web at the moment. 36 00:02:24,350 --> 00:02:26,330 And whoa, does this make me feel nervous. 37 00:02:26,330 --> 00:02:26,850 So, let's do this. 38 00:02:26,850 --> 00:02:31,870 Let's make sure that no matter what, this will never ever be shown, 39 00:02:31,870 --> 00:02:36,651 never ever exported, we're gonna put a @JsonIgnore on there. 40 00:02:36,651 --> 00:02:38,323 So we feel pretty good about that but 41 00:02:38,323 --> 00:02:40,960 how do you feel about storing that password in a string. 42 00:02:40,960 --> 00:02:43,669 I mean if somebody gets a hold of the object they could just get a hold of 43 00:02:43,669 --> 00:02:44,296 the password. 44 00:02:44,296 --> 00:02:45,766 I don't feel very good about that. 45 00:02:45,766 --> 00:02:48,973 Sometimes people use the same password across multiple services and 46 00:02:48,973 --> 00:02:51,840 that's just not good to have the password exposed. 47 00:02:51,840 --> 00:02:55,090 So, I was thinking maybe we could just store an encrypted version of it. 48 00:02:55,090 --> 00:02:57,590 Now, again, Springs Security has her back. 49 00:02:57,590 --> 00:03:01,720 So a common approach is to expose a password encryptor on your 50 00:03:01,720 --> 00:03:02,740 entity as a constant. 51 00:03:02,740 --> 00:03:03,330 So let's do that. 52 00:03:03,330 --> 00:03:06,457 So let's make a private or, no, actually, I'm sorry. 53 00:03:06,457 --> 00:03:11,222 Let's make a public, so you know that people to use this, 54 00:03:11,222 --> 00:03:13,956 static final PasswordEncoder. 55 00:03:18,262 --> 00:03:19,647 Cool, we need to refresh our Gradle also, 56 00:03:19,647 --> 00:03:21,230 in those that we're talking about, don't we? 57 00:03:23,420 --> 00:03:27,030 So used to having that on auto that, all right, so 58 00:03:27,030 --> 00:03:29,400 now it should know what we're talking about. 59 00:03:29,400 --> 00:03:29,900 That's it. 60 00:03:31,230 --> 00:03:32,432 That is not it. 61 00:03:32,432 --> 00:03:35,520 And PasswordEncoder and we can choose that, here we go. 62 00:03:36,700 --> 00:03:42,830 And for now, let's just make that a new BCryptPasswordEncoder. 63 00:03:42,830 --> 00:03:44,970 More on the teacher's notes if you want. 64 00:03:44,970 --> 00:03:49,400 All right, so let's go ahead and we'll make a Setter for 65 00:03:49,400 --> 00:03:54,930 that password field that just goes ahead and uses an encryptor. 66 00:03:54,930 --> 00:04:00,480 So you pass in the string Password and we're gonna go ahead and encode it. 67 00:04:00,480 --> 00:04:02,600 Okay, no matter what is set for 68 00:04:02,600 --> 00:04:05,100 that password encoder, this is kind of a common practice. 69 00:04:06,440 --> 00:04:10,903 Phoo, I feel a lot better, okay and we're also going to do a little 70 00:04:10,903 --> 00:04:14,860 authorization like what the user is allowed to do. 71 00:04:14,860 --> 00:04:17,216 So, we'll do that using a role-based system. 72 00:04:17,216 --> 00:04:20,240 So, let's just add some simple strings that will represent our roles. 73 00:04:20,240 --> 00:04:23,022 Now, they probably don't ever wanna show those either. 74 00:04:23,022 --> 00:04:28,310 So let's do this, let's make a new @JsonIgnore field and 75 00:04:28,310 --> 00:04:33,196 we'll say private, just use a string array, right? 76 00:04:33,196 --> 00:04:34,830 We can do that, we'll say, roles. 77 00:04:34,830 --> 00:04:40,959 Okay, let's go ahead and we can generate all the getters and setters. 78 00:04:42,740 --> 00:04:47,496 And we definitely don't wanna push those other to, we can do the, well, 79 00:04:47,496 --> 00:04:51,580 password that we pass out will be encrypted, so that's okay. 80 00:04:51,580 --> 00:04:57,231 So we're gonna pass all that stuff up, here we go. 81 00:04:57,231 --> 00:04:59,824 And again, it's not gonna come out across the web but 82 00:04:59,824 --> 00:05:03,568 if you have access to the user object which should be something that we trust, 83 00:05:03,568 --> 00:05:06,210 Tthey'll have access to get hold of these things. 84 00:05:06,210 --> 00:05:09,270 Once we generate a new constructor that basically takes everything. 85 00:05:09,270 --> 00:05:14,720 And then in the constructor instead of setting the password this way, 86 00:05:14,720 --> 00:05:19,886 let's call this password, let's just call set password. 87 00:05:19,886 --> 00:05:22,849 And we'll set it with the password that came in, right, 88 00:05:22,849 --> 00:05:26,820 the password that we passed will be plain text, then we'll do that across. 89 00:05:28,180 --> 00:05:34,120 And remember it's an entity so we need to make a protected User and 90 00:05:34,120 --> 00:05:39,150 it calls super, and then we need to make sure that this calls that, all right. 91 00:05:39,150 --> 00:05:43,770 This we're gonna call our protected user for whatever set up is that. 92 00:05:43,770 --> 00:05:44,680 Awesome. 93 00:05:44,680 --> 00:05:45,850 Okay, that's feeling pretty good. 94 00:05:45,850 --> 00:05:48,220 Let's go ahead and make our repository. 95 00:05:48,220 --> 00:05:53,670 So we'll make a new Java Class and we'll set it to an interface and 96 00:05:53,670 --> 00:05:57,645 what we're gonna do here is it will be called the UserRepository. 97 00:05:59,850 --> 00:06:04,108 And it is going to extend 98 00:06:04,108 --> 00:06:10,340 the CrudRepository and 99 00:06:10,340 --> 00:06:14,170 that is of type User, and the ID is Long. 100 00:06:20,080 --> 00:06:21,760 Okay, so here's the thing. 101 00:06:21,760 --> 00:06:22,790 If we don't do anything, 102 00:06:22,790 --> 00:06:28,170 our API is going to export this repository just like it did for courses in reviews. 103 00:06:28,170 --> 00:06:30,900 And we don't want someone just browsing our users, do we? 104 00:06:30,900 --> 00:06:32,750 It seems like pretty bad form. 105 00:06:32,750 --> 00:06:37,540 So, what we want to do is we want to use spring data because it's awesome, right? 106 00:06:37,540 --> 00:06:42,375 It's gonna generate all the querying but we don't want to have it restified, right? 107 00:06:42,375 --> 00:06:44,822 So, why don't we just use this annotation. 108 00:06:44,822 --> 00:06:51,657 So we're gonna do this, we're gonna say @RepositoryRestResource, 109 00:06:51,657 --> 00:06:55,920 and we gonna pass exported = false. 110 00:06:55,920 --> 00:07:01,092 Now this doesn't exist, there is no slash users off our API. 111 00:07:01,092 --> 00:07:03,976 Now, we're gonna be having the user enter their username and password. 112 00:07:03,976 --> 00:07:07,198 So in order to get spring security wired up correctly, 113 00:07:07,198 --> 00:07:10,620 let's expose a finding by username method, right? 114 00:07:10,620 --> 00:07:16,040 So that will return a user and it will be fined by username and 115 00:07:16,040 --> 00:07:18,090 again because of that naming thing, it's just gonna work. 116 00:07:18,090 --> 00:07:21,800 We're gonna say (String username), awesome. 117 00:07:21,800 --> 00:07:23,100 That will come in handy in a bit. 118 00:07:23,100 --> 00:07:27,790 Okay and now finally let's add the relationship between the review and 119 00:07:27,790 --> 00:07:28,760 the user, okay? 120 00:07:28,760 --> 00:07:35,395 So let's go to the review and right here, it's a many to one, right? 121 00:07:35,395 --> 00:07:38,780 One user can have many reviews. 122 00:07:38,780 --> 00:07:42,900 So let's say private User reviewer. 123 00:07:44,370 --> 00:07:48,770 And let's go ahead and come down here and we'll generate the getter for that so 124 00:07:48,770 --> 00:07:53,360 that we can use it if we want to. 125 00:07:53,360 --> 00:07:54,690 Let's do the getter and the setter. 126 00:07:57,215 --> 00:07:58,610 Okay, this is feeling good. 127 00:07:58,610 --> 00:08:01,912 What do you say we generate some users in our database loader? 128 00:08:01,912 --> 00:08:05,199 Okay, so let's go over to our database loader and 129 00:08:05,199 --> 00:08:08,738 now we can set proper reviewers for each one of these. 130 00:08:08,738 --> 00:08:11,682 So let's add a list of users that will call students and 131 00:08:11,682 --> 00:08:15,260 we'll add them using that arrays as a list static method. 132 00:08:15,260 --> 00:08:17,800 Now, I sent out a call to the Twitters and 133 00:08:17,800 --> 00:08:20,470 I added them to the teacher's notes here for inclusion. 134 00:08:20,470 --> 00:08:24,067 So, go ahead, go down to the teachers notes and grab the students who were so 135 00:08:24,067 --> 00:08:26,520 nice to let us share their name for test data. 136 00:08:26,520 --> 00:08:31,591 Thank you everybody for helping our tester application. 137 00:08:31,591 --> 00:08:32,895 So I'm gonna paste that here. 138 00:08:32,895 --> 00:08:36,470 Let's make sure that it knows what we're talking about, okay? 139 00:08:36,470 --> 00:08:41,810 And we also need to import our user repository that we just created, 140 00:08:41,810 --> 00:08:47,720 so we're gonna say, final UserRepository, and we'll call that users. 141 00:08:47,720 --> 00:08:49,400 Of course, it's gonna complain. 142 00:08:49,400 --> 00:08:52,200 And what we'll do is we'll add it as a constructor parameter. 143 00:08:55,272 --> 00:08:55,920 There we go. 144 00:08:58,240 --> 00:09:02,852 So, now we can go ahead and 145 00:09:02,852 --> 00:09:07,856 call users.save(students). 146 00:09:07,856 --> 00:09:09,160 Awesome. 147 00:09:09,160 --> 00:09:10,822 So now all those users are in our database, 148 00:09:10,822 --> 00:09:12,300 I'm gonna actually add myself too. 149 00:09:12,300 --> 00:09:16,709 So let's say, users.save(new 150 00:09:16,709 --> 00:09:22,522 User("craigsdennis", "Craig", 151 00:09:22,522 --> 00:09:28,620 " Dennis" and my password that I'm gonna use, the same one I use for my luggage. 152 00:09:28,620 --> 00:09:33,078 "12345" and we'll do a new String. 153 00:09:33,078 --> 00:09:39,030 And I'm gonna give myself, not only am I gonna give myself the user role, 154 00:09:39,030 --> 00:09:41,830 I'm also gonna give myself the admin role now. 155 00:09:41,830 --> 00:09:42,910 I just made that word out. 156 00:09:42,910 --> 00:09:46,630 We haven't done anything defining what admin actually means, yet. 157 00:09:46,630 --> 00:09:47,990 You can call it whatever you want. 158 00:09:47,990 --> 00:09:51,200 I just wanna create a role that can do anything, basically. 159 00:09:51,200 --> 00:09:54,960 So, eventually we'll make it, so anybody who has admin can do whatever they want, 160 00:09:54,960 --> 00:09:57,060 but for right now this is just a word. 161 00:09:57,060 --> 00:09:59,120 Okay, so let's do this. 162 00:09:59,120 --> 00:10:01,650 Let's extract this review. 163 00:10:02,680 --> 00:10:10,230 Let's do a Refactor > Extract > Variable. 164 00:10:12,740 --> 00:10:15,026 What's the reason that didn't work? 165 00:10:15,026 --> 00:10:18,670 I have the wrong amount of stuffs selected there. 166 00:10:18,670 --> 00:10:20,048 There we go. 167 00:10:20,048 --> 00:10:25,362 We gonna choose Refactor > Extract > Variable, 168 00:10:25,362 --> 00:10:31,880 here we go and we're gonna call that the review there. 169 00:10:31,880 --> 00:10:38,859 And so what we need to add is we need to now that we have this review, 170 00:10:38,859 --> 00:10:42,364 going to say review, setReviewer. 171 00:10:42,364 --> 00:10:43,714 And we're gonna use the same trick. 172 00:10:43,714 --> 00:10:48,173 We're going to say students.get, and 173 00:10:48,173 --> 00:10:53,288 index is going to be (i % students.size), 174 00:10:53,288 --> 00:10:56,450 a little module math there. 175 00:10:56,450 --> 00:10:59,088 And you know what I noticed right here when I pasted this out? 176 00:10:59,088 --> 00:11:04,240 This actually needs to be, this could return 0 which is not what we want. 177 00:11:04,240 --> 00:11:11,439 So we want, there we go, instead of being 0 to 4, we want to be 1 to 5. 178 00:11:11,439 --> 00:11:15,666 Modulo math, this is probably too many parentheses, don't do that. 179 00:11:15,666 --> 00:11:18,080 When we added the dependency to spring security, 180 00:11:18,080 --> 00:11:19,807 spring boot does what it does best. 181 00:11:19,807 --> 00:11:21,969 It automatically configured our API to be secure. 182 00:11:21,969 --> 00:11:26,531 Now, the problem with that is that we have no way for the users to currently log in. 183 00:11:26,531 --> 00:11:31,240 So, let's take a quick break and swing back and configure spring security to use 184 00:11:31,240 --> 00:11:35,990 our new user entity for both authentication and authorization. 185 00:11:35,990 --> 00:11:39,550 Now is a probably a good time to go take a quick stroll, 186 00:11:39,550 --> 00:11:42,940 this next little bit is going to take some focused typing. 187 00:11:42,940 --> 00:11:45,840 So I recommend that you approach it calm and refreshed. 188 00:11:45,840 --> 00:11:49,580 Don't worry, I'll be right here waiting for you just like Richard Marx, but 189 00:11:49,580 --> 00:11:50,700 without the mullet. 190 00:11:50,700 --> 00:11:51,200 See you in a bit.