GitHub Repository

We already made progress in this direction. In the second part, we created the index.html file and included Angular in our project. We now have to add the remaining missing libraries and kickstart the UI.

Using the code above, we create the LoginController needed for our route. In it, we inject the $state and a new service called authService. We haven’t created that service yet, but we plan to abstract some of the login logic inside of it.

Next, we initialize the loginError flag and the loginErrorMessage values on the view model. We will use these later to notify the user about failed login errors.

Following, we define a single public method on the view model called login, which does a couple of things:

First, it will reset the error flags — in case there was any error set.

Next, it will check if the view model username or password are both provided. If not, it sets the flags accordingly.

Finally, if everything went well, it will use the authService to pass the username and password and continue the login action.

The authService.login() method is expected to return a promise. If the promise resolves, it will redirect the user to the index route. Otherwise, it will notify the user and set the response message as the error message.

Let’s go back to our state and add the missing template markup for our login form.

The markup above defines a form with two inputs for the username and password and their models.

Below the page heading, we are using the loginError flag to control whether or not to display an alert. Its content will be the loginErrorMessage view model value.

Finally, we specify that the login() method should run when the user clicks the Login button.

Before we can test this in the browser, we need to create the missing authService and include the missing scripts in our document.

Authentication Service

To keep repetition to a minimum and our controllers simple, we can abstract most of the authentication logic inside a service. We’ll call it authService and we will place it inside the app/services folder.

# app/views/index.html

Accessing the http://localhost:8080/login route we can now see the ugliest login form ever.

If I attempt to login with a non-existent user, I receive an error. Good!

Using a real user, I get redirected to the index state. Perfect! I also checked if the cookie is set correctly and wasn’t disappointed.

User Area (Profile)

After logging in, it would be great if I could access my profile page that would display some details. More exactly, the greeting we set to be returned on the /api/profile endpoint. We can make a route for this!

Before proceeding, don’t forget to include the profileController.js file inside index.html.

It won’t work just yet cowboy! If you were eager to jump into testing mode and loaded the /profile page, you’ve seen that you’re not getting anything from the server just yet other than an Unauthorized error in the console.

This happens because, in order to access the /api/profile endpoint, we need to pass the token in the request.

Request Interceptor

Using a request interceptor, we can intercept every request we make and check if there’s a logged in user. During this time, we can also attach the token to the Authorization header. Easy enough!

Let’s write it right before the staticData constant in the app.js file.

In the run block, we’re listening to the $stateChangeStart event and check if the state that needs to load has an accessLevel value defined.

If it does, we’re using the same piece of logic we used on the server to check if the current user’s role allows it. If not, we redirect that sneaky bastard to the index state.

To retrieve the logged in user’s data, we’re using a method called getUserData from our authService which is curently missing.

When getting the user’s data, we will also need to check if there is actually a user logged in. Since this is a common task, it would be best if we moved the logic into a separate function. Who knows? Maybe we want to use it in the future.

Inside the SignupController we define a signup() method that does the following:

Sets the appropriate flags

Checks the username and password

Uses the authService.signup() method to create a new account.

Note: We’re not validating the form the best way here. Instead, a good practice would be to use the Angular way. To learn more, make sure you check out this cool article about AngularJS Form Validationon Scotch.io.

# /app/services/authService.js

The function removes the stored cookie and redirects the user to the index state.

After making sure all missing scripts are included in the index.html file, we can go ahead and try out the new navigation.

Conclusion

Congrats on making it this far! We finished our small project and I would like to thank you for following me this far. During this three-part series we’ve tested our full stack skills and managed to create a role based user authentication system using a bunch of cool libraries. Using our creativity we can take this further and extend it.

Don’t be shy! Share your thoughts about this post or ask for help if you’re stuck in the comments below. I’ll be glad to assist.

Sharing is Caring

If you 💖 this post, I’d appreciate if you’d let your friends know about it too. You can use the floating buttons to share this post on various social networks. Thanks! 🙂

Alex M

Hi Catalin, many thanks for the tutorial.
It seems that you have read my mind, because I need to start a project using Sequelize and Node this week. Well I have some doubts:

1) When I try to access localhost:8080/profile or ./admin once I’m user or admin role, it makes a redirection to index page and isn’t showing anything. Do you know what could be the problem?

2) As I’ve told you, next week I’ll need to start a project in my Intern Job using Node and SQL BD, so my tutor said me that I could probably need to use Sequelize. For me Using Node/Express/Angular is new because I’ve worked only with PHP using Symfony2. So your small auth app is perfect for me to start. However I have some pre-requisites that I need to satisfy. One of them is to manage the ROLES directly in the database with a Model for that, linked to USER Model. As I’ve seen, you manage all the Roles in the controller, so I would like to know how should I start handling this issue?
The Schema DB should Looks like:
User Role RoleAsign <– Permissions

Hello Alejandro! I’m glad to find that it helped you. Regarding your first problem, please check the console and see if there’s an error. Otherwise, make sure you followed my examples accordingly or even check the code I commited in the repo. Regarding your second request, I’m afraid the code required for the functionality you describe goes beyond the scope of this tutorial or what I can do to help you here.

Alex M

Console log doesn’t display none, only it makes a redirection to de “/” page. I have used the code from your repo and it fails.

Now it works, but only is comparing if there are a user logged in. And there aren’t ROLE parameters in the cookie stored, only there is a token, so you need to use this: “if(!(user.token))” instead of “if(!(user.role))”.

Great catch! You are right, there is a redirect issue, yet the problem is not caused by that if statement. In that case it’s important to check the user’s role and not the token. The problem has its roots on the server where currently only the token is returned after a user is authenticated (in the AuthController.authenticateUser method). The ‘user.token’ being undefined there results in a redirect to the index route. I just pushed a fix for this. 😀 Make sure you check it out and please let me know if I can assist you with anything else.

Rama Astadipati

Hi @hiskie:disqus, is there any idea to make a real REST api with this ?

Kamil gündüz

hello, i am new at web programming, and i am intrested in reactjs these days. may i use backend code of this project with react-redux frontend? i am asking that question because i am still trying to understand web development concepts.

Rani Somu

Thanks for the article. It’s really very helpful.
Could you guide me to do one more api from authenticated user’s profile page. For example, after login display user’s mark details in report table format.
Thanks in advance.