Subscribe to our email newsletter for useful tips and valuable resources, sent out monthly.
Thank you! You have successfully signed up for our newsletter.
Oops! Please confirm your've entered a valid email address.
Blog.
In our previous blog post, we tackled app presentation and how to use CoreUI to add an admin template to your app. At this point, you should have a strong app architecture, but as we all well know a chain is only as strong as its weakest link, which in this case refers to your app security vulnerabilities. Authentication and authorization problems are consistently ranked amongst the top three most critical security risks to web applications in the OWASP Top 10, thus to mitigate these risks we’ll be guiding you through the process of adding backend and frontend authentication to your application.
Preparation
Before we can tackle authentication, we first need to create a new branch and environment where changes can safely be made. In your project folder, type the following command:
cd [project_folder] git checkout develop git checkout -b feature/auth
This command will create a new git branch called feature/auth and switch context to that branch. Next we’ll create a new AWS environment where we can add and configure the backend authentication. Type the following command in the project root:
amplify env add
At this point, you’ll be asked to answer a few questions. Simply copy the answers below and Amplify will start doing its magic to create the necessary CloudFormation code to build our new app environment.
Q: Do you want to use an existing AWS environment (Y/N)?
A: No. (We want to create a new environment where we can add and update cloud services without affecting our current working environment.
Q: Enter a name for the environment
A: auth
Q: Do you want to use an AWS profile?
A: Yes. (We’ll use the profile created in the configuration step).
Q: Please choose the profile you want to use
A: scribe
Adding Backend Authentication
We’ll be using AWS Cognito to add the authentication service to our app. We’ll be running the following command to add the authentication service to our new environment:
amplify add auth
The command will trigger a set of configuration questions:
Q: How do you want users to be able to sign in
A: Username
Q: Do you want to configure advanced settings?
A: No, I am done. (For the time being we’ll just be going with the basic username option).
If you’re still up to speed, running the amplify status will display the following:
Amplify has added a folder (amplify/backend/auth/) to our project to keep the backend auth configuration settings. For the moment this is only a local change. Lets commit the changes to git and push the auth service into the cloud.
When asked if you want to continue, answer “yes” as this will push the changes through to AWS.
Configure Amplify In Angular
To integrate the frontend let’s install the aws-amplify and aws-amplify-angular packages. Aws-amplify is the AWS Amplify core library, while Aws-amplify-angular is one of the AWS Amplify library packages which provides building blocks for Angular App development.
npm install aws-amplify-angular
If you are using an Angular 6+ version add the following code to the polofill.ts file.
(window as any).global = window; (window as any).process = { env: { DEBUG: undefined }, };
When adding the backend authentication service using AWS Cognito, Amplify creates a file called aws-exports.js in the src directory. This file contains all the configuration needed for your angular app to connect to the AWS Cognito service. To implement this in your application add the following to your main.ts file:
// src/main.tsimport Amplify, { Auth } from 'aws-amplify';import amplify from './aws-exports';Amplify.configure(amplify);
At this point we’ve configured Amplify and can use it in the rest of our Angular application. Add the following to include Amplify in the application:
In the previous segment there were two views included when we added CodeUI to our application, login and register views. Building on these views, we’ll register a new user first.
Registration
Let’s create two components here to handle the registration flow; one component for registering and one for confirming the registration. AWS Cognito has built-in functionality for registering and confirming the account with a confirmation code, which is automatically sent to the account’s email address. To create the register form component, execute the following command in the root of the project:
ng g component components/register-form
This will create a register form component at src/app/components/register-form.
Copy the following code into src/app/components/register-form/register-form.component.ts:
import { Component, EventEmitter, OnInit, Output } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Auth } from 'aws-amplify'; import { Router } from '@angular/router'; @Component({ selector: 'app-register-form', templateUrl: './register-form.component.html', styleUrls: ['./register-form.component.css'] }) export class RegisterFormComponent implements OnInit { registerForm: FormGroup; submitted = false; @Output() cognitoUser = new EventEmitter(); constructor( private formBuilder: FormBuilder, private _router: Router ) { } ngOnInit() { this.registerForm = this.formBuilder.group({ email: ['', [Validators.required, Validators.email]], password: ['', [Validators.required, Validators.minLength(6)]], confirmPassword: ['', Validators.required], }); } // Convenient getter for easy access to form fields get f() { return this.registerForm.controls; } onSubmit() { this.submitted = true; // stop here if form is invalid if (this.registerForm.invalid) { return; } // Call the Cognito signUp method Auth.signUp({ "username": this.registerForm.get('email').value, "password": this.registerForm.get('password').value, "attributes": { "email": this.registerForm.get('email').value } }) .then(data => { console.log(data); // Emit the successful response from Cognito // This will be picked up by the view in order to show the // confirm form. this.cognitoUser.emit(data); }) .catch((error: any) => { console.log(error); switch (error.code) { case 'UsernameExistsException': this._router.navigate(['login']); break; } }); } }
That takes care of the component. Add the below code to the src/app/components/register-form/register-form.component.html:
This takes care of the view which contains a form with three fields (username, password, confirmPassword). We’ll be using an email for the username and pass that to AWS Cognito as the username and email for the new user.
Confirm Form Component
Create the confirm form component by executing the following command in the root of the project.
ng g component components/confirm-form
This will create a confirm form component at src/app/components/confirm-form.
Copy the following code into src/app/components/confirm-form/confirm-form.component.ts:
import { Component, Input, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Auth } from 'aws-amplify'; import { Router } from '@angular/router'; @Component({ selector: 'app-confirm-form', templateUrl: './confirm-form.component.html', styleUrls: ['./confirm-form.component.css'] }) export class ConfirmFormComponent implements OnInit { confirmForm: FormGroup; submitted = false; @Input() email: string; constructor( private formBuilder: FormBuilder, private _router: Router ) { } ngOnInit() { this.confirmForm = this.formBuilder.group({ email: [this.email, [Validators.required]], confirmation_code: ['', [Validators.required]] }); } get f() { return this.confirmForm.controls; } onSubmit() { this.submitted = true; // stop here if form is invalid if (this.confirmForm.invalid) { return; } Auth.confirmSignUp(this.confirmForm.get('email').value, this.confirmForm.get('confirmation_code').value) .then(data => { console.log(data); this._router.navigate(["login"]); }) .catch((error: any) => { console.log(error); switch (error.code) { case 'UsernameExistsException': break; } }); } }
That takes care of the confirm form component code. Add the below code to the src/app/components/register-form/register-form.component.html:
This takes care of the confirm form view which contains a form with two fields (email, confirmation_code). The email will be returned from the registration code as part of the AWS Cognito signup response. The confirmation code, which is sent on signup, will need to be entered in the form in order to confirm the registration.We need to update the register view which was added to our application in the CodeUI step. Override the register component with the following code:
At this point we’ve registered a user and confirmed the registration. The next thing we need to do is to hook up the login form to make use of AWS Cognito to authenticate the newly registered user.
Login
To create the login form component, execute the following command in the root of the project:
ng g component components/login-form
This will create a login form component at src/app/components/login-form.
Copy the following code into src/app/components/login-form/login-form.component.ts
import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Auth } from 'aws-amplify'; import { Router } from '@angular/router'; @Component({ selector: 'app-login-form', templateUrl: './login-form.component.html', styleUrls: ['./login-form.component.css'] })export class LoginFormComponent implements OnInit { loginForm: FormGroup; submitted = false; constructor( private formBuilder: FormBuilder, private _router: Router ) { } ngOnInit() { this.loginForm = this.formBuilder.group({ username: ['', [Validators.required]], password: ['', [Validators.required]] }); } get f() { return this.loginForm.controls; } onSubmit() { this.submitted = true; // stop here if form is invalid if (this.loginForm.invalid) { return; } Auth.signIn(this.loginForm.get('username').value, this.loginForm.get('password').value) .then((data: any) => { console.log(data); this._router.navigate(['dashboard']) }) .catch((error: any) => { console.log(error); }); } }
Add the following code to the login form component’s html file to create the view for the component.
Now we want to make user of this component within the Login View which exists inside the CodeUI files we added. To do this we need to override the Login View as below:
// views/login/login.component.html<div class="app-body"> <main class="main d-flex align-items-center"> <div class="container"> <div class="row"> <div class="col-md-8 mx-auto"> <div class="card-group"> <div class="card p-4"> <div class="card-body"> <app-login-form ></app-login-form> </div> </div> <div class="card text-white bg-primary py-5 d-md-down-none" style="width:44%"> <div class="card-body text-center"> <div> <h2>Sign up</h2> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <button type="button" class="btn btn-primary active mt-3">Register Now!</button> </div> </div> </div> </div> </div> </div> </div> </main> </div>
Wrapping Up
Run the following command to add all the new files added during this topic and commit it to your git repository:
git add . git commit -am "Add authentication"
Now we want to merge the code into our develop branch to bring all the authentication updates into our develop branch:
Run amplify status to see the status of the current environment:
amplify status
At this point, you should be able to see the following:
Run the following command to deploy the changes to the dev environment:
amplify push
When asked if you are sure that you want to continue, answer “yes”. After this step, we’ll remove the resources from the feature branch by running the following command:
amplify env remove auth
Testing
After following the steps outlined above, we can go ahead and test our app authentication features.
Enter your email address and password in the register form.
Successful registration will trigger an email containing the confirmation code:
Once you’ve confirmed your account registration you can login to the application. At the login screen, enter your email in the username field and enter your password.
If you followed the steps correctly, successful login will direct you to the CoreUI dashboard.
Where To From Here?
After adding backend and frontend authentication to your Angular application, there will still be a bit of work left such as handling incorrect login credentials and hooking up forgotten passwords, but the essential architecture will be in place. Keep an eye on our social media accounts or sign up for the Swipe iX newsletter to stay up to date with our latest tutorials, as we’ll be walking you through the process of guarding your application next. If you have any questions, get in touch, but for now we’ve concluded this tutorial on how to sign up and sign in, so for now - we’re signing out.
Swipe iX Newsletter
Subscribe to our email newsletter for useful tips and valuable resources, sent out monthly.
Thank you! You have successfully signed up for our newsletter.
Oops! Please confirm your've entered a valid email address.