Two-Factor Overview0:00
Okay, let's take a look at two-factor authentication. So quick review of how it works in Jetstream. In our profile, we can enable it here, and we have to confirm our password. And now, a few things happen here. We have our QR code, which we have to scan, so it goes into our Google Auth app on our phone. A bunch of recovery codes are generated here. You can use this as well to log in. You can also disable it and regenerate the recovery codes. So these features correspond to these routes here.
You can also disable it and regenerate the recovery codes. So these features correspond to these routes here. So let me do route list. So we have all of these routes here, which correspond to those features that I just showed you. Now, let me grab one of the recovery codes. And definitely make sure to scan this if you want it in your Google Auth app, but I'm just going to use the recovery code to log in. So I'm copying this one here, and let me log out and log in. And now I should be redirected to a two-factor challenge after I enter my correct password.
Create Profile Page1:33
So make sure you remember that, because we'll take a look at that later on. There are two forms there. Okay. So let's start with the profile part of enabling two-factor auth in profile. So let's go ahead and work on that. So let's go into our Fortify example. Let's make a new route. Let's just duplicate one of these ones. Duplicate this one, actually. profile.
Duplicate this one, actually. Profile. Yeah, let's duplicate this one, since it goes in here. Let's call it two-factor-auth.blade.php. Okay, let's just change this to two-factor-auth. There's some errors here, and a session status, and we'll change this in a second. Let's add that route to our routes file. two-factor-auth. Let's call it two-factor-auth. two-factor-auth.
Let's call it two-factor-auth. two-factor-auth. Okay. And let's also add it to our menu. So that would be an app.blade.php. Let's add it after password. Say two-factor-auth. two-factor-auth. Oops. And same here.
Enable/Disable Two-Factor2:46
Oops. And same here. Okay. So let's open that up. There we go. So first thing I want to do is enable two-factor-auth. So if you go back to Jetstream, let me just disable it. I guess I have to enter my password again. Let's just have an enable button here and enable two-factor-auth. So let's set that up.
Let's just have an enable button here and enable two-factor-auth. So let's set that up. Back to our view here. So the route for that is this one here. So user/two-factor-authentication. And to disable it, it's a DELETE request. So we'll do enable and disable first. So the endpoint is, what did I say, user/two-factor-authentication. Okay. Let's paste that in.
Okay. Let's paste that in. I think I copied it. Okay. And it's a POST request. So let's remove this. And all we need is the button to submit it. And let's say enable here. Okay. And let's also grab the success message in the session.
Okay. And let's also grab the success message in the session. And I believe that's in the docs here. Oh, yeah. We have to do this as well. So we have to set up our User model to make sure it includes this two-factor-authenticatable trait. So let's make sure to add that. Let me grab this. Let's go to our User model.
Let me grab this. Let's go to our User model. And let's add it here. And let's make sure to import that. And there we go. And back here, it says by default, it makes use of the password confirmation, which we did in the last video. And just to show you that, if you go to the fortify.php config, Fortify, you'll see that there's this confirms password option here. Okay.
this confirms password option here. Okay. Back to the view. Where's the view? Here we go. And I'm trying to grab the session. Here we go. The status. So the status is this if it's enabled. And we're just displaying a message.
So the status is this if it's enabled. And we're just displaying a message. So we can grab that. And let's put it in our success message here. So instead of this, we're going to paste that in. Okay. So let's save that. And before I click the enable button to see if it works, let's check our database. So let me refresh. I'm currently logged in as this User right here.
So let me refresh. I'm currently logged in as this User right here. And as you see, there is no two-factor secret or two-factor recovery codes. So that means two-factor-auth is currently off. So if I did this correctly, when I click that, let's go to two-factor-auth. And if I hit enable, we should get the confirm password. And we do. And I'm not sure if that worked. It didn't show the success message. Let's check our database.
It didn't show the success message. Let's check our database. No, it didn't work. As you can see, this is still null. So what did I do wrong? Actually, let me try it again. So this time it worked. I'm not sure why it didn't work the first time. You can see the success message there. And now if I refresh this, you'll see the two-factor secret and the recovery codes.
You can see the success message there. And now if I refresh this, you'll see the two-factor secret and the recovery codes. So that means it's on. So now I want that enable button to show as disable. So we just have to do a conditional in here. So let's go ahead and do that. So to check if it's enabled, unfortunately, there's no isTwoFactorAuthEnabled check on the User model. So we just have to do something else. So let's make a Blade conditional here.
So we just have to do something else. So let's make a Blade conditional here. So all we have to do is check if the User, so we'll do auth()->user() for the logged in user, if it has the twoFactorSecret column. So if it's not null, actually, for this case, since I have not, this is the null case. And we want to enable it. And we already have that case. So I'll just put that in there. And then for the else case, we can do the delete request. So it's the same thing, but it's a delete request.
And then for the else case, we can do the delete request. So it's the same thing, but it's a delete request. So I'm going to copy this, paste this, or you can put the conditional on the delete request, but I'm just going to do the whole form. So it's a delete request. So let's do method delete and let's change this to disable. So this should show now since it's enabled. Okay. And when I press disable, these two should be null. Okay, so that's working.
Show QR and Codes8:21
And we want to show this somewhere above the form. So somewhere here and make sure to escape it. So we want to use the exclamation or not escape it, I mean, because this will render, I believe, an image tag with an SVG or maybe just a raw SVG. Yeah, it's probably a raw SVG. And we only want to show this when it is enabled. So we can duplicate this and do this. So when two-factor auth is enabled and I forgot to paste it in. So let's paste that in. There should be the loggedInUser.
I'm just going to show you what it's rendering. Okay. And let's try that out. And you can see we get this encrypted string over here, but we want to display the recovery codes. So even if we cast it like it shows here, it still doesn't work. So if I do array here, still won't work. Let's try that. Now we still get the same thing or we get an error. So to actually get the recovery codes, let's actually just check what Jetstream is doing.
Now we still get the same thing or we get an error. So to actually get the recovery codes, let's actually just check what Jetstream is doing. So let me switch to that project. This is a two-factor authentication form, and you'll see it somewhere in here. So right here, we have to json_decode it, decrypt it, and that should display the codes. Actually, I'm going to grab this entire foreach. So it displays each code in its own div. So back to our project. Let's just paste that in. And this should work and display the recovery codes.
Let's just paste that in. And this should work and display the recovery codes. I'm sorry, we have to change this to User twoFactorUser. Okay. And there we go. There are the recovery codes. Let's add one more button here to regenerate the codes if we want to do that. So the endpoint for that, if you look at our routes again, is this one here. So user.twoFactorRecoveryCodes. So I'm going to grab that.
So User two-factor recovery codes. So I'm going to grab that. Let's go back to our code and duplicate this and move it up. And let's make another div here for this section over here. Okay. And let's add the form for that. Okay. And the endpoint is /whatever is in my clipboard User two-factor recovery codes. And let's change the text to regenerate codes. Okay.
And let's change the text to regenerate codes. Okay. See if this works. Let's refresh. Regenerate codes. And you should see this generate a new list of codes if I did it right. And I did. Cool. Okay. So that should be all the setup within our profile for two-factor auth.
Build Challenge Screen12:26
Okay. So that should be all the setup within our profile for two-factor auth. So let me just grab one of these codes so we can test it out in a second. Let me just paste it somewhere else just in case I lose it. And now if we look at our routes, we have to make use of these two-factor challenge routes. So this is when we actually log in. So if you look at the docs, we have this section for authenticating with two-factor auth. We have to do the same thing here. You have to add this to define the view.
We have to do the same thing here. You have to add this to define the view. So let's do that. FortifyServiceProvider. Let's add that down here. Again, I'm going to change this to short closure syntax. Okay. Let's save that. And let's go ahead and make this view. So that should be within the auth folder.
And let's go ahead and make this view. So that should be within the auth folder. And let me just duplicate one of these. Let's duplicate this one. Let's say two-factor-challenge.blade.php, okay? And change the title to enter your code here for two-factor auth. And the errors are fine. And the status is fine. We're not going to see a status because if it's correct, then it will just redirect us into the dashboard.
We're not going to see a status because if it's correct, then it will just redirect us into the dashboard. So the form. So like I showed you earlier, we should have two forms here. One for using the two-factor auth code and one for using the recovery code. And you would use JavaScript to toggle between them like I showed you in Jetstream. So the endpoint is two-factor challenge. And it's a POST request. So let's add that. It's just a two-factor challenge without the user.
So let's add that. It's just a two-factor challenge without the User. So let's type that in here. Two-factor challenge. And for the code, the Google Authenticator code, the field we need is named code. So let's change this to code, okay? And I'm not going to bother auto-focusing it. Sorry, this should be text. And the other form is going to duplicate this same endpoint, but the field is recovery_code. So let's change these to recovery_code.
And the other form is going to duplicate this same endpoint, but the field is recovery_code. So let's change these to recovery_code. And we can change this to recovery code, okay? And depending on which form you submit, it will use the correct one. So we'll test both out. So let's go ahead and log out, log out, and log in. Go ahead and log in, andre@andre.com, password. And now, if I did everything correctly, we should see that new form we created. Sorry, it's not the right user, new@new.com, okay? And now we get that form we just created.
Test Login Challenge16:13
We should be redirected to our screen. Let me open up the app on my phone, and there should be a code in there. Okay, so the code showing is this, 906233. And if that's correct, it should log us in. It does. Cool. So yeah, if you want to make use of two-factor auth with apps like Google Authenticator, Fortify makes it really easy.
