WEBVTT 00:01.910 --> 00:06.500 So we have emails going out properly, but of course, the biggest problem with the email is the link 00:06.500 --> 00:11.570 we have that is supposed to allow people to reset their password is just a link to a university, and 00:11.600 --> 00:12.540 that's not helpful. 00:13.280 --> 00:18.590 So we want to be able to send a link to the front end that will show a form that allows people to choose 00:18.590 --> 00:19.330 a new password. 00:19.340 --> 00:22.120 And of course, we want that to be absolutely secure. 00:22.730 --> 00:26.090 In other words, we don't want to make that open to just anyone. 00:26.480 --> 00:30.530 Now, obviously, we can have people log in to change the password because they don't know what the 00:30.530 --> 00:31.250 password is. 00:31.760 --> 00:37.580 So what we need is some means of securing that to make sure that the only people who have access to 00:37.580 --> 00:40.250 the link are people who should have access to the link. 00:40.880 --> 00:42.740 Now, there's a number of ways of doing this. 00:42.740 --> 00:49.000 One really common method is to append a unique token to the email or to give them a token. 00:49.010 --> 00:51.250 They have to enter into a form or something like that. 00:52.130 --> 00:56.950 And of course, you look up that token in the database and verify that it's valid and so on and so forth. 00:56.960 --> 00:58.370 And that seems like a lot of work. 00:58.680 --> 01:05.810 What I'm going to suggest we do instead is to use signed emails, emails which have an actual hash or 01:05.810 --> 01:12.190 some kind of code in the euro itself that will ensure that you are simply can't be changed. 01:12.440 --> 01:16.760 And we'll also make sure that an email expires after a set length of time. 01:16.920 --> 01:18.120 So let's get started doing that. 01:18.410 --> 01:24.440 What I'm going to do is take you to a package, one that I've been using for years, and it works really, 01:24.440 --> 01:25.010 really well. 01:25.490 --> 01:30.790 And it's called right here, B.W. Marengo alone. 01:30.890 --> 01:36.200 And as you might be able to tell from the actual picture here in the name of it, it's dangerous to 01:36.200 --> 01:36.710 go alone. 01:36.860 --> 01:42.140 Clearly, this is written by someone who really enjoys games that involve characters named Link and 01:42.140 --> 01:42.620 Zelda. 01:43.130 --> 01:47.420 Setting that aside, this is a really simple package and it works really, really well. 01:47.420 --> 01:48.950 And you can go through the source code. 01:48.950 --> 01:53.930 It's heavily commented and it's only a couple of hundred lines of code, but I'm going to use this package, 01:54.200 --> 01:55.280 so let's go get it. 01:55.550 --> 02:05.660 We'll find the installation link right here and go back to our ID and open our terminal and paste that 02:05.660 --> 02:06.020 in. 02:06.110 --> 02:08.540 Go get and then the link to the package. 02:11.160 --> 02:16.770 OK, so it's installed now, it's real, it's relatively straightforward to use this package, and what 02:16.770 --> 02:22.890 I'm going to do is create a new internal package that uses the functionality from the go alone package. 02:23.160 --> 02:28.420 And that way, if I need to sign something either on the front end or on the back end, I can do so. 02:28.830 --> 02:36.540 Now, if we go back and look at the documentation we need, as you can see right here, some kind of 02:36.540 --> 02:37.640 secret key. 02:38.250 --> 02:39.870 So we're obviously going to have to define that. 02:39.880 --> 02:44.730 And of course, the easiest way to do that is either to use an environment variable or to use a command 02:44.730 --> 02:46.720 line flag, and I'll use a command line flight. 02:47.250 --> 02:51.850 Let's go back to our idea and think about what we're going to do here. 02:52.350 --> 02:59.340 This link is going to be something like whatever the link to our front end is some kind of path and 02:59.340 --> 03:00.600 then however it's signed. 03:01.050 --> 03:02.490 So we're going to need two things here. 03:02.520 --> 03:04.110 We're going to need that secret key. 03:04.110 --> 03:10.440 And we're also going to need in our backend some reference to or some way of knowing what the world 03:10.440 --> 03:11.730 to our front end is. 03:11.760 --> 03:16.610 So let's go over to aiport, go and put that necessary logic in place. 03:17.790 --> 03:23.250 So the first thing I'll do is go to our config struct and again, I'm on API go the main entry point 03:23.250 --> 03:27.270 for the back end and I'll add two new members here, secret key, 03:32.310 --> 03:33.210 which will be a string. 03:34.170 --> 03:40.110 And also I'll call the next one the front end, which is sufficient for my purposes and it will be a 03:40.110 --> 03:40.470 string. 03:40.560 --> 03:47.010 So this will be the key that we use to sign our URLs and this will be the address for our front end. 03:47.170 --> 03:49.460 OK, so we need to get that information. 03:49.470 --> 03:55.320 So let's get down to the flag part and I'll just copy this one because it's a reading a string version 03:57.180 --> 04:01.430 and I'll paste it twice and I'll give it default values, which will make it easier for me. 04:02.400 --> 04:03.960 So I'm going to read into. 04:05.010 --> 04:13.440 CFG secret key, and we'll give it the command line flag of secret, which is sufficient, I'll just 04:13.440 --> 04:16.110 put some random characters in here just to make it work. 04:17.860 --> 04:20.280 And of course, you can generate whatever you want for this. 04:20.880 --> 04:24.740 And for the hint, we'll simply just call this secret key. 04:26.160 --> 04:34.910 And for the next one, we want the front end URL, which is front end, and we'll call this front end. 04:34.920 --> 04:35.810 That'll be the flag. 04:36.300 --> 04:42.240 And in my case, it's called an localhost for four thousand. 04:43.740 --> 04:49.140 And we'll give the hint of your URL to front and back. 04:49.860 --> 04:54.660 So now we have a means of specifying our secret key and our front end, and we have sensible default 04:54.660 --> 04:59.010 values that I can use for development so I don't have to type those in every time I want to run the 04:59.010 --> 04:59.550 application. 04:59.920 --> 05:05.700 Now, let's go over to our internal folder and I'll create a new package. 05:06.480 --> 05:17.010 So a new folder and I'm going to call mine You URL seiner and I'll create a new filing there called 05:17.190 --> 05:18.080 Sinor Dongo. 05:19.770 --> 05:22.890 And of course, it is the package of old Sinar. 05:26.040 --> 05:30.570 And we'll make this a very simple package to use, so the first thing we do is to find a type which 05:30.570 --> 05:33.600 we can use to actually create this type of Zeiner. 05:34.900 --> 05:35.980 That's what I'm calling it. 05:36.390 --> 05:39.670 It's a struct and it only has one field secret. 05:40.530 --> 05:44.070 If you look at the documentation, the secret has to be a slice of bytes. 05:44.610 --> 05:50.110 Now, I'll create a few functions here and each one will have the receiver pointing to the sinor type. 05:50.130 --> 05:59.640 So the first one as the receiver of Seiner and I'll call it, generate token from string. 05:59.910 --> 06:06.150 And what this will do is take a string and sign it and hand back the sign strength so it takes some 06:06.150 --> 06:09.240 data which is a string and it returns a string 06:12.240 --> 06:14.590 and I'll just mixed up functions for the rest of them. 06:15.060 --> 06:21.380 So we'll also have one with the receiver of Seiner and I'll call this one Verify Token. 06:21.540 --> 06:27.920 And this is what we use to verify that the link people click on hasn't been changed in any way. 06:28.950 --> 06:34.080 And it takes a token, which is a string and it returns bool, true or false. 06:35.550 --> 06:41.970 And finally, we'll have another one with the receiver of S pointer designer. 06:44.770 --> 06:50.200 And this one will check to see if tokenized expired because we can put expiry dates on these and it 06:50.200 --> 06:58.360 takes a toll, which is a stream, and it takes minutes until they expire, which is a long name, but 06:58.360 --> 06:59.470 it's very clear what it means. 06:59.500 --> 07:00.340 And that's an integer. 07:00.640 --> 07:01.840 And again, that returns a little. 07:02.920 --> 07:04.460 So let's start on this one at a time. 07:04.690 --> 07:14.350 So the first one, I'm going to create a variable, which I'll call you to sign, and it's just a string. 07:16.300 --> 07:17.140 So there's a variable. 07:17.950 --> 07:19.570 And now I'll call create a variable called 07:23.080 --> 07:28.810 and it is assign the value of from the go alone package, which we just important. 07:30.040 --> 07:31.390 We may have to manually import. 07:31.420 --> 07:32.430 We'll find out shortly. 07:34.640 --> 07:35.080 New. 07:37.020 --> 07:42.580 Authorities found it, and that takes a secret, which is estcourt secret. 07:43.670 --> 07:50.500 From our receiver, and it also takes a time stamp go along the time stamp. 07:51.680 --> 07:52.520 That's just a constant. 07:54.270 --> 07:57.080 Now, what kinds of users might we get? 07:57.380 --> 07:58.810 What this package does? 07:58.820 --> 08:04.550 And you can see it right on the homepage, is it will take a string and append a question mark and some 08:04.550 --> 08:05.530 kind of value to it. 08:05.540 --> 08:11.270 And what I want to do instead is allow us to sign new URLs that already have your URL parameters. 08:11.270 --> 08:12.310 They already have a question mark. 08:12.320 --> 08:21.290 So much you can do a little comparison here, a little check if from the strings package contains if 08:21.290 --> 08:23.570 the string we want to sign contains. 08:23.840 --> 08:31.520 So data is the first item and it contains a question mark, then I want to do one thing, otherwise 08:32.570 --> 08:33.600 I want to do something else. 08:33.980 --> 08:42.500 So if it contains that question mark, then I'll make Yoro to some equal to from the format package. 08:44.320 --> 08:45.130 As per death 08:47.980 --> 08:49.870 and my string is going to be. 08:53.250 --> 08:56.400 S ampersand hash equals, 09:00.780 --> 09:05.700 and I'll substitute data for my placeholder, so this will take care of the situation where I'm trying 09:05.700 --> 09:08.280 to you, where all that already has your URL parameters. 09:08.850 --> 09:17.530 But if it doesn't contain a question mark, then you URL to sign is equal to formatter as print f then 09:17.550 --> 09:21.750 I get a string percent s questionmark hash equals. 09:23.140 --> 09:23.790 And then data, 09:27.790 --> 09:30.550 and now we need some bytes, so token bites. 09:31.300 --> 09:39.040 This is the part where we're signing our email is Creped dot sign and we need to cast to a slice of 09:39.040 --> 09:39.520 bytes. 09:41.110 --> 09:42.510 You to sign, 09:45.480 --> 09:53.370 and our token is equal to string looking votes, because we want to return to strength and we'll return, 09:53.370 --> 10:00.520 the token and token has to have the assignment operator there. 10:01.500 --> 10:03.410 So our token is not just a token. 10:03.420 --> 10:09.780 It's a fully signed euro that ends with hash equals, plus the bit that we're going to use to validate 10:09.780 --> 10:10.530 that you are up. 10:10.550 --> 10:12.490 So there's our first one taken care of. 10:13.050 --> 10:15.800 Now, our second one verified token is actually pretty simple. 10:16.560 --> 10:17.190 Same thing. 10:17.820 --> 10:19.120 We need our creped here. 10:19.140 --> 10:27.260 Someone is going to copy this line and paste it in here and you get a response. 10:27.270 --> 10:33.990 I'm going to ignore the actual first return parameter, but I am going to check for an error and we're 10:33.990 --> 10:36.530 going to call Creped site. 10:37.110 --> 10:40.920 And that require requires an actual token, which we receive. 10:40.920 --> 10:43.220 It's a parameter here, but that needs to be a slice of bytes. 10:43.230 --> 10:45.240 So slice of byte 10:48.210 --> 10:49.080 and we check for an error. 10:50.460 --> 10:52.290 If error is not equal to nil, 10:55.650 --> 10:58.940 then I'll print out there just so we can see what's going on. 10:58.950 --> 11:06.450 So format the print line error and I'll return false. 11:09.540 --> 11:13.110 Otherwise we successfully verified it turned true. 11:15.360 --> 11:19.980 And the third one where we check for an expiry date again, we need our creped, which I still have 11:19.980 --> 11:21.780 on my clipboard, so I'll just pasted in there. 11:23.470 --> 11:25.860 That gives us access to the go alone methods. 11:27.120 --> 11:30.120 And this is dead simple test as a time stamp. 11:30.610 --> 11:40.260 It's a sign the value of creped dot purse and we need to pass what we received in this function, which 11:40.260 --> 11:45.180 is a token and that has to be Casta, a slice of white and it's token. 11:48.190 --> 11:59.930 And we return time since not Saturday, since right from the time package, our time stamp to start 11:59.960 --> 12:09.820 time stamp is greater than time, duration and its minutes until expire. 12:12.390 --> 12:23.340 Times, time, up minute, so this will return true if the expiry date is OK and false if the expiry 12:23.340 --> 12:24.250 date is not OK. 12:24.270 --> 12:28.620 In other words, you only have 60 minutes to act on the link that you clicked on. 12:28.620 --> 12:31.950 But sixty one minutes have gone by, so we're going to return false. 12:32.310 --> 12:39.450 So there's our package now in the next lecture will actually use this package in our handler's dash 12:39.450 --> 12:41.940 API and sign a valid email.