JWT Authentication Setup

Kent C. Dodds
InstructorKent C. Dodds

Share this video with your friends

Send Tweet
Published 8 years ago
Updated 3 years ago

Setting up a login on the angular app and an authentication endpoint on the server.

Man 1: [00:01] Here we have an app where we can get random users. Our goal for this video is to add authentication to this application.

[00:09] The first thing that we're gong to need is a form. Instead of an action we'll have an ng-Submit="vm.login(vm.username, vm.password)."

[00:18] Then we'll have an ng label input with the out label of Username and the type is text and the model is vm.username. Then we'll have another one of these for password. It will be a type password. We'll also add a break to make things look nice. Then we'll have a button with login and it's type submit.

[00:39] Let's go to our app. We'll have a vm.login = login. Login takes a user name and password. We'll create a user factory that will have the login. That takes the username, password. Then we'll say VM.user equals the data that we get back.

[00:58] In case of failure, we're going to make a simple function called handleError. We'll define that here. That will take a response and it will simply alert ('Error: ' + response.data). We'll use that function here, as well.

[01:12] Let's create this user factory, app.factory Userfactory. Function login takes your user name and password and it will return $HTTP.get. Actually, it will be a post because we're locking. We're going to post the data. API_URL/login and the data will be userName, userName, password, password.

[01:36] Then we'll export that and we'll inject HTTP_API_URL. Then we'll want to inject the user factory here.

[01:46] Let's go ahead and refresh. We have user name, kentcdodds and cannot post a login because we haven't created that yet but we can still get these users. That's important for now.

[01:55] We'll go to server and we'll make a login. App.post/login. Now we need to authenticate the user. We're gong to ass a middleware function here, authenticate. We'll have our util functions. Authenticate will be one of those that takes a request, a response.

[02:13] And then, next, now we need to be able to read the .JSON that comes back in the requests. Specifically the user name and password.

[02:21] To do that we're going to install a module called body-parser. That will give Express the ability to parse the body that comes in. We'll require body-parser, and just like with CORS, we'll say, App.use(bodyParser.json()).

[02:36] Now we have a body on the request. If there's not a body.username or not a body.password then we'll send with a response, "Status of 400 must provide user name or password."

[02:52] Now we need to have a user name and password to check against. Normally you would obviously store all of your users in a database but in our case, just to make things simple, we're going to make a mini database here that's just of our user = object with the username kentcdodds and a password P.

[03:11] If the body.username is not equal to the user.username or the body.password it not equal to the user.password then we'll send her a status of 401, "User name or password incorrect."

[03:30] Then we'll send them to the next function handler.

[03:33] If they made it this far we know that they are authenticated. We'll simply send the user back. We'll refresh the page. Now, if we log in you see we've got no error. If we look in our network tab here we'll try and log in again.

[03:45] We hit the log in and let's make this big here. Look at the preview. We have the password and user name. We have the whole user object.

[03:53] Obviously, generally you wouldn't want to send a password over the wire but we'll just be simple for now.

[03:58] That's a simple log in authentication. We can still hit the endpoint to get random users. We can still get the random user here.

[04:07] Our next video is going to be protecting this resource behind authentication. That's where we'll start to use JWS.

Kent C. Dodds
Kent C. Doddsinstructor
~ 7 years ago

So I'm not certain what trouble you're having, but in my example, the handleError function is not attached to the scope (and certainly not $rootScope). The reason it works is because the second argument to a promise's .then function is a function that is called on an error. Good luck!

adr
adr
~ 7 years ago

Sorry I just deleted the post after finding my error and before your answer :/ It was a noob error from my part ^^ I had like form /form with the labels after... I was going to fast when coding cause you're really fast lol Thanks anyway, really good serie !

Kent C. Dodds
Kent C. Doddsinstructor
~ 7 years ago

Glad you got it figured out! Thanks!

David Mansy
David Mansy
~ 7 years ago

Hi Small detail. With the illustrated code, I had a node error in the server console: Error: Can't set headers after they are sent.

This happened when you deal with a usern/pwd error case, you trigger a res.end but at the end of the function res.send is anyway executed.

To solve that I've just added 'else if' and 'else' in the code of the 'authenticate' function: ''' if (!body.username || !body.password) { res.status(400).end('Must provide username and password!'); } else if (body.username !== user.username || body.password !== user.password) { res.status(401).end('Username or password is incorrect.'); } else { next(); } '''

A
A
~ 7 years ago

Dear Kent Thank you for your course. You are very good developer and your content is very good but I am very frustrated that I cannot type fast like you and please review Lukas Ruebbelke course format. I was able to finish his 2 courses very fast. Please change something because for this reason I am avoiding Joe Eames classes on pluralsite. You really good in what you do but please change something. I really want to learn from you and there is no speed control. Also at the begging of each lesson explain what are you trying to do.

Kent C. Dodds
Kent C. Doddsinstructor
~ 7 years ago

Thanks for the compliment and feedback.

A
A
~ 7 years ago

Kent - I want to thank you for your class. It helped me a lot in my last project (last 5 days). I reviewed it even 2 nd time. Keep doing what you doing!

Carlos Andres
Carlos Andres
~ 7 years ago

Which would be a better practice to send username and password? I'm sending it via headers in this way: authorizationHeader = "Basic " + btoa(email + ":" + passphrase); JWT could serve for this purpose ? how?

Kent C. Dodds
Kent C. Doddsinstructor
~ 7 years ago

That's not how I do it in this series. And I wouldn't recommend doing it that way. You don't want your JWT to contain sensitive information because it can be decoded without the private key.

Robert
Robert
~ 7 years ago

function authenticate(req, res, next) { var body = req.body;

console.log(body.username);

not getting the value says "undefined."

inlightmedia
inlightmedia
~ 6 years ago

In server.js, if the authentication "UTIL function" responds to the request by sending a 400 or 401 it continues to next() and tries to set the response header again at line 23 res.send(user) and results in an error in the console stating that you "Can't set headers after they are sent." How can this be avoided. I could conditionally call next() only if there were no error headers sent but I get the feeling I'm doing more than I should need to and I'm missing something.