1 00:00:02,170 --> 00:00:05,530 Now as I mentioned, Firebase has authentication built-in, 2 00:00:05,530 --> 00:00:11,350 wWe just need to go to the authentication area there and then click on setup sign in method and there 3 00:00:11,350 --> 00:00:16,500 choose password and email or e-mail password here. Enable this and click save 4 00:00:16,600 --> 00:00:18,550 and with that, we have it enabled. 5 00:00:18,550 --> 00:00:25,640 Now we can send requests to a Firebase API to create users or to log them in. Now in order to find 6 00:00:25,640 --> 00:00:27,140 out where to send the requests, 7 00:00:27,140 --> 00:00:32,630 you can google for Firebase REST Auth API and you will find these official docs where you'll learn 8 00:00:32,630 --> 00:00:36,180 how to create and sign in users with their API. 9 00:00:36,210 --> 00:00:40,820 Now there are a bunch of endpoints for different things, here in this app we'll focus on signing up and 10 00:00:40,820 --> 00:00:41,440 signing in. 11 00:00:41,540 --> 00:00:45,200 So if we click on sign up with e-mail and password, we learned how that works. 12 00:00:45,290 --> 00:00:52,250 We need to send a HTTP request, a post request with this content type to this URL, enter our own 13 00:00:52,280 --> 00:00:58,890 API key here which I'll show you where you get it from in a second and attach this body to the request, 14 00:00:58,910 --> 00:01:05,180 so e-mail password and then this return secure token field which should basically always be true. As 15 00:01:05,180 --> 00:01:10,820 a response, we'll get back a token, that's that token I mentioned on the slide, the email we used, 16 00:01:10,940 --> 00:01:13,790 a refresh token which is more advanced, 17 00:01:13,790 --> 00:01:19,430 this token here will expire actually after this amount of seconds which we also get back. With a refresh 18 00:01:19,430 --> 00:01:22,350 token, we could recreate it, revalidate it 19 00:01:22,910 --> 00:01:26,460 without having the user to login again, we'll not do that here, 20 00:01:26,570 --> 00:01:31,100 you would have a separate endpoint to which you send the refresh token to get a new ID token, 21 00:01:31,100 --> 00:01:37,310 we'll keep it simple here and just use that token and log the user in again after that expiry time because 22 00:01:37,310 --> 00:01:39,080 that expiry time is also something we get 23 00:01:39,080 --> 00:01:43,880 so that we know when this token will become invalid and can't be used anymore because we'll have to clean 24 00:01:43,880 --> 00:01:49,850 it up in our app by then, so that we don't try attaching this invalid token to future requests to our 25 00:01:49,850 --> 00:01:56,600 database and localId, that's the userId of the user which Firebase created on its servers because 26 00:01:56,600 --> 00:02:02,050 we do not have to do any of that user management, Firebase will do that, we don't need to write any server-side 27 00:02:02,060 --> 00:02:03,380 code. 28 00:02:03,440 --> 00:02:07,610 So what we need to do is send a HTTP request 29 00:02:07,610 --> 00:02:13,340 and since I also will manage this all with Redux, I will create a new action creator for this and I'll 30 00:02:13,340 --> 00:02:14,500 name it auth. 31 00:02:14,510 --> 00:02:20,720 I will also already create a reducer because we will also manage some auth related stuff there, for example 32 00:02:20,720 --> 00:02:22,790 the token and the userId. 33 00:02:23,090 --> 00:02:25,980 Let's start with the action though and let's 34 00:02:26,510 --> 00:02:31,810 hence export an action creator here which could be named sign up, 35 00:02:31,940 --> 00:02:37,070 makes sense to start with that because logging users in will only be possible after we created at least 36 00:02:37,070 --> 00:02:40,130 one user. So here in sign up, 37 00:02:40,130 --> 00:02:44,590 I want to be able to create a new user and for that, we'll need an email and a password 38 00:02:44,600 --> 00:02:50,420 so that should be passed to the sign up action creator from outside. 39 00:02:50,690 --> 00:02:56,750 Now then, this will send a HTTP request and in order to be able to do that, we'll use the Redux Thunk 40 00:02:56,750 --> 00:03:01,180 package again and therefore return async dispatch here, 41 00:03:01,460 --> 00:03:07,970 so we return a function which can use async await which gets that that dispatch function as an argument 42 00:03:08,000 --> 00:03:14,150 passed in by the Redux Thunk middleware we started using in the last HTTP module of this course and 43 00:03:14,150 --> 00:03:20,480 this allows us to run async code before we then dispatch an action that actually reaches our store. 44 00:03:20,620 --> 00:03:25,940 Now for that, we'll also need an action identifier for that action which we later want to handle in our 45 00:03:25,940 --> 00:03:31,590 store and there I'll just use sign up, which also has sign up as a string identifier. 46 00:03:31,850 --> 00:03:39,290 So here in the end, we'll then dispatch this action object where the type is sign up and where we will 47 00:03:39,290 --> 00:03:45,940 probably then also add some extra data but before we do that, we need to send a HTTP request. 48 00:03:46,020 --> 00:03:51,170 Now that can be done with the fetch API as you learned in the last module and definitely go through 49 00:03:51,170 --> 00:03:52,360 that module first 50 00:03:52,370 --> 00:04:01,130 therefore and this is the URL we need to send the request to, so we can copy that. Add it here and 51 00:04:01,130 --> 00:04:03,700 now we have that API key thing. 52 00:04:04,220 --> 00:04:07,240 Now that's something we can get from Firebase by clicking on the gear 53 00:04:07,250 --> 00:04:09,700 icon here, project settings. There 54 00:04:09,760 --> 00:04:13,450 you'll find the web API key and that's exactly what you need, 55 00:04:13,460 --> 00:04:19,680 copy that and replace API key including the square brackets with that key. 56 00:04:19,700 --> 00:04:25,970 This is the URL we will need to send a request to. Now as the official docs tell us, we need to send a post 57 00:04:25,970 --> 00:04:26,870 request, 58 00:04:26,990 --> 00:04:30,950 so as you learned, we need to add this second argument here to fetch 59 00:04:30,950 --> 00:04:36,680 which is an object which allows us to configure that request and there, we can set the method to post 60 00:04:37,280 --> 00:04:44,180 and also add some headers because we'll need to add the application JSON header, so the content type 61 00:04:44,180 --> 00:04:52,130 header which should have a value of application JSON and we'll need to add a body and that body needs 62 00:04:52,130 --> 00:04:58,700 to be in JSON format which we can get with JSON.stringify and the data I want to stringify needs to 63 00:04:58,700 --> 00:05:07,660 be an object with these three keys - email, password and return secure token. So here of course, email refers 64 00:05:07,660 --> 00:05:14,890 to the email we're getting as an argument here, the same for password which refers to the password argument 65 00:05:14,890 --> 00:05:22,060 we're getting and then it's this third and I'll just copy it to not mistype it, 66 00:05:22,060 --> 00:05:29,770 return secure token argument here or key-value pair where the value should just be true. This request 67 00:05:29,770 --> 00:05:31,770 should create a new user. 68 00:05:31,900 --> 00:05:38,530 Now we can wait for its response with the await keyword and then as you learned earlier, we can check 69 00:05:38,620 --> 00:05:46,660 if the response is not okay, if that's the case, I want to throw a new error where I say something went 70 00:05:46,930 --> 00:05:55,340 wrong and we'll have a look at more detailed error handling later, for now that's it and if it is okay 71 00:05:55,380 --> 00:06:02,970 however, I want to get my response data by awaiting for response JSON which will unpack the response 72 00:06:02,970 --> 00:06:09,780 body and automatically transform it from JSON format to Javascript, so to a Javascript object or array 73 00:06:10,500 --> 00:06:16,200 and now we will be able to work with that and for the moment, I'll simply log this response data here. 74 00:06:17,910 --> 00:06:23,590 Now we haven't added the rest of our auth related Redux store, we'll do that later but we have something 75 00:06:23,590 --> 00:06:28,840 that should work, we should be able to dispatch this and therefore send such a sign up request. 76 00:06:28,840 --> 00:06:36,460 So now we can go back to the auth screen and there in the end when we click this login button which 77 00:06:36,460 --> 00:06:41,770 is incorrectly labeled login at the moment when we actually do sign up but let's leave it like this 78 00:06:41,770 --> 00:06:42,420 for the moment, 79 00:06:42,460 --> 00:06:50,330 so when we click this button I want to send this sign up request. So for that, we need to, as before, import 80 00:06:50,390 --> 00:06:55,810 use dispatch from React Redux so that we can dispatch actions 81 00:06:56,150 --> 00:07:05,810 and of course, import everything as auth actions from the store folder data, from the actions folder and 82 00:07:05,810 --> 00:07:09,590 there from the auth file 83 00:07:09,840 --> 00:07:13,170 and with that added, we can add a function here, 84 00:07:13,190 --> 00:07:17,880 either an inline function or like this, a named function stored in a constant 85 00:07:18,410 --> 00:07:20,850 which I'll name sign up 86 00:07:20,990 --> 00:07:23,240 handler, there 87 00:07:23,250 --> 00:07:27,780 I expect no arguments and there I then want to dispatch, 88 00:07:27,780 --> 00:07:33,590 so we need to get access to that dispatch function by executing use dispatch and 89 00:07:33,650 --> 00:07:36,090 then here we can dispatch 90 00:07:36,210 --> 00:07:40,860 this auth actions sign up event or sign up 91 00:07:40,860 --> 00:07:41,410 action. 92 00:07:41,430 --> 00:07:44,430 Now the problem is this requires the email and the password 93 00:07:44,430 --> 00:07:46,020 and right now I'm not storing this. 94 00:07:46,020 --> 00:07:51,500 I get this in my input but here on input change, I'm not storing that data which I of course should. 95 00:07:51,570 --> 00:07:56,320 Now we can have a look at our other form here to see how we did that. 96 00:07:56,370 --> 00:08:06,760 So in the edit product screen, we of course have our form reducer here which manages our entire form related 97 00:08:06,910 --> 00:08:08,670 validity and the values. 98 00:08:08,800 --> 00:08:15,790 So in the end, we can copy that and add it to the auth screen outside of the auth screen component like this 99 00:08:16,990 --> 00:08:24,140 and go back to the edit product screen to then also grab the part down there where we initialize that 100 00:08:24,140 --> 00:08:25,400 with use reducer, 101 00:08:25,430 --> 00:08:28,970 so copy all of this and add it to the auth screen as well, 102 00:08:28,970 --> 00:08:38,730 now inside of the component, maybe here and for that to work, we also need to import use reducer from 103 00:08:38,730 --> 00:08:40,350 React 104 00:08:40,480 --> 00:08:46,140 and with that imported, now we just need to tweak it a little bit. This form reducer is fine 105 00:08:46,150 --> 00:08:51,160 and by the way you could outsource this into a separate file because we're using the same type of reducer 106 00:08:51,400 --> 00:08:53,860 in both the auth screen and the edit product screen, 107 00:08:53,860 --> 00:08:57,160 you could even create a custom hook if you know how that works, 108 00:08:57,160 --> 00:08:59,180 for now I'll just leave it like this. 109 00:08:59,230 --> 00:09:01,560 One thing I need though is the form input update, 110 00:09:01,570 --> 00:09:04,620 let me grab that from the edit product screen as well, 111 00:09:04,630 --> 00:09:05,810 this constant here, 112 00:09:05,830 --> 00:09:08,020 let's move that in auth screen as well. 113 00:09:08,980 --> 00:09:09,670 So now with that, 114 00:09:09,670 --> 00:09:15,190 that's all fine but down there where I call use reducer and initialize this all, that of course looks 115 00:09:15,190 --> 00:09:16,470 differently. 116 00:09:16,630 --> 00:09:22,120 We should have an email which initially is empty and a password which initially is empty and for the 117 00:09:22,120 --> 00:09:23,720 validity, it's the same, 118 00:09:23,800 --> 00:09:28,690 we just have an email which initially is not valid and we have a password which initially is 119 00:09:28,690 --> 00:09:33,310 not valid and the overall form therefore also initially is not valid. 120 00:09:34,570 --> 00:09:40,240 Now dispatch form state should be triggered whenever our input changes here, 121 00:09:43,290 --> 00:09:49,830 so here in on input change, of course you know and you can see it in the edit product screen, 122 00:09:49,830 --> 00:09:55,230 we get three values - we get the input identifier, the input value and the input validity. 123 00:09:56,100 --> 00:10:03,630 So in the end we can just copy this here from edit product screen and move it to the auth screen and 124 00:10:03,630 --> 00:10:10,630 replace this anonymous function with it or actually store this in a new variable here, 125 00:10:10,770 --> 00:10:18,620 input change handler which now holds this function. Now just as in the edit product screen, you 126 00:10:18,620 --> 00:10:24,620 should grab this with use callback to make sure that this doesn't rerender when it shouldn't. 127 00:10:24,620 --> 00:10:31,190 So actually, we should grab it here including the use callback call and the dependencies of use callback, 128 00:10:31,250 --> 00:10:38,360 so this is actually what should be used down there on the input change handler. 129 00:10:38,460 --> 00:10:45,690 Now this input change handler can be bound or can be set here to the on input change props so that 130 00:10:45,720 --> 00:10:48,340 these props target this function 131 00:10:48,840 --> 00:10:55,740 and now with that, we're storing our form values or our input values in our form state which we handled 132 00:10:55,740 --> 00:10:59,370 with use reducer and so on. 133 00:10:59,380 --> 00:11:04,630 So now it's this form state I'm interested in here in my sign up handler because there to sign up, 134 00:11:04,630 --> 00:11:11,830 I need to pass from state input values.email and form state input values.password, 135 00:11:11,840 --> 00:11:18,850 so these two values which were gathered and now the sign up handler here, this function can be bound to 136 00:11:18,850 --> 00:11:24,320 this button down there, to the login button here in onPress because this is the function I want to point at 137 00:11:24,560 --> 00:11:28,160 to execute it when we press this button. 138 00:11:28,410 --> 00:11:34,810 Let's see whether that works as it should. If I start entering values here, 139 00:11:38,160 --> 00:11:42,750 I do get my validation errors but somehow they're not showing up, 140 00:11:44,040 --> 00:11:50,950 that's the case because it's not error message here but error text on the inputs in the auth screen. 141 00:11:51,060 --> 00:11:54,920 So if we change that error message to error text, 142 00:11:55,020 --> 00:11:58,460 now if we test this, so if I click in here, tap out of there, I get my warnings. 143 00:11:58,500 --> 00:12:00,960 Now if I enter a valid e-mail address, this is gone, 144 00:12:00,960 --> 00:12:08,350 if I enter a password that's long enough, that's gone, if I now click login here, let's see whether that 145 00:12:08,350 --> 00:12:08,740 works. 146 00:12:08,740 --> 00:12:14,880 Let's go to Firebase, to authentication and there, you now should see a new user, 147 00:12:14,950 --> 00:12:17,360 this is the user which just was created. 148 00:12:17,530 --> 00:12:19,810 So signing up works, 149 00:12:19,810 --> 00:12:24,060 now let's make sure we can also switch to login mode and make that work as well. 150 00:12:25,100 --> 00:12:28,970 By the way, also note that this here is the data we got back, 151 00:12:29,030 --> 00:12:30,150 so that's the response, 152 00:12:30,150 --> 00:12:31,810 this object with email, 153 00:12:31,880 --> 00:12:32,300 how long 154 00:12:32,300 --> 00:12:34,440 the token is valid in seconds, 155 00:12:34,550 --> 00:12:40,220 then the token itself which is this long cryptic string, then also the ID of the user which was 156 00:12:40,220 --> 00:12:41,960 created and that refresh token.