Angular User Registration & Login using Busywork as a Backend
Tags: angular, tutorial, webdev, backend
Published: 2020-02-06 19:06:51

[Busywork is a backend-as-a-service](https://busywork.co) that allows you to assemble the backend functions you need for your web app, in minutes. Busywork comes with a fully-managed database and storage. Within Busywork you can add already built modules to your backend or build from scratch. 

In this tutorial, I will show you how to use Busywork to create:

- User Sign Up
- User Sign In
- User Sign Out

## Table of Contents
* [Setting up Busywork](#p1)
* [Setting up Angular 8](#p2)
* [User Authentication Service](#p3)
* [Setting the Access Token](#p4)
* [Guarding Content](#p5)
* [Sign Up Component](#p6)
* [Sign In Component](#p7)
* [Profile Component](#p8)
* [Conclusion](#p9)

# Step 1: Setting Up Busywork <a name="p1"></a>

![Sign Up with Busywork](https://dev-to-uploads.s3.amazonaws.com/i/ys5h613xqiltlmti3u5u.png)

Go to https://busywork.co/sign-up/ and register. It has a free plan that contains all the features that we need for this tutorial.

Once signed in, go to *Builds* where you'll see all of the backend functions we need for this tutorial.

![User authentication functions](https://dev-to-uploads.s3.amazonaws.com/i/q4122dh60c5b7vaksk1j.png)

The already created functions serve as simple examples of what you can make in Busywork. Feel free to discover other and more complex flow that for instance allow you to send a welcome email, add a user to your CRM system and ...

# Step 2: Setup an Angular 8 Project <a name="p2"></a>
To get started we need to create a new Angular project. We'll be using the Angular CLI tool to create the new project. Run the following command:

`ng new busywork-user-authentication`

Which will prompt you about routing and which styling you want to use:

```
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? SCSS   [ https://sass-lang.com/documentation/syntax#scss                ]
```

Now we have to change the directory to our newly created Angular project.


`cd busywork-user-authentication`

For this tutorial, we'll need to create a few components:

- Sign Up Component
- Sign In Component
- Profile Component

Create the components by running the following commands.

```
ng g c user/sign-up
ng g c user/sign-in
ng g c user/profile
```

Finally, we will be using Bootstrap 4 to provide some styling to our components and elements. Add it to your project by running this command.


`npm i bootstrap`

Add the Bootstrap style to your project by adding the following line in the **angular.json** file.

```json          
"styles": [          
    "node_modules/bootstrap/dist/css/bootstrap.min.css",
    "src/styles.scss"
]
```


Now you are ready to start your app.

`ng serve`

# Step 3: User Authentication Service <a name="p3"></a>
We now create a service that we will use as an abstraction for our Busywork functions. Inside the `user` folder we create a service called **authentication**.

`ng g s user/authentication`

We are consuming the Busywork API using AJAX calls, so we need to make the **HttpClientModule** available within the service. In **app.module.ts** import the module.

`import { HttpClientModule } from "@angular/common/http";`

And add it to the **imports** section of the module declaration. 

```typescript
imports: [
  .
  .
  HttpClientModule,
  .
  .
],
```

First, we initialize some variables that we'll be using throughout the methods in the service.

```typescript
// your busywork workspace URL
workspace = 'http://gracious-lamport-58c4db.busywork.ai';
// JSON header
jsonHeader = {headers: new HttpHeaders({'Content-Type':  'application/json'})};
```

Next, we create methods for:
- Getting the users access token
- Signing up the user
- Signing in the user
- Signing out the user
- Authenticating the user

## Get Access Token
We'll be using the local storage for storing the user's access token once obtained. We need to access the token later, so we make a handy helper function inside the authentication service.

```typescript
getAccessToken(){
  return localStorage.getItem('user_access_token');
}
```

## Sign Up User
To sign up a user we need to invoke the appropriate Busywork function: `this.workspace + '/sample-sign-up'`. Inside Busywork you can see the required arguments of the function. We need a **username** and **password** to sign up a user.

```typescript
signUp(username:string, password:string){
  return this.http.post(
    this.workspace + '/sample-sign-up',
    // body content - required args can be seen in the Busywork function
    {
      'username': username,
      'password': password
    },
    this.jsonHeader
  );
}
```

When we get a response from the Busywork API we can choose what to do if the user has been signed up or if the sign up failed.

## Sign In User
Signing in the user is done in the same way - we send **username** and **password** to the Busywork function. But with this function, we want to store the user's access token if the sign-in is successful. 

```typescript
signIn(username:string, password:string){
  return this.http.post(
    this.workspace + '/sample-sign-in',
    // body args
    {
      'username': username,
      'password': password
    },
    this.jsonHeader
  ).subscribe(
    (result:any) => {
      // save the access token in local storage
      localStorage.setItem('user_access_token', result['access_token']);
      // save the user id in local storage
      localStorage.setItem('user_id', result['user_id']);
      // change route to the profile component
      this.router.navigate(['profile']);
    }
  )
}
```

Finally, if the user has signed in we redirect the user to the profile page.

## Sign Out User
For sign-out, we don't need to send any data to the function. The function only needs the access token, which will be included in the request header.

```typescript
signOut(){
  return this.http.post(
    this.workspace + '/sample-sign-out',
    {},
    this.jsonHeader
  ).subscribe(
    (result:any) => {
      this.router.navigate(['sign-in']);
    }
  )
}
```

## Authenticating the User
This service method is used to check with the Busywork API if the user's access token is valid. A user's access token is invalid if it has either expired or been revoked on sign-out.

```typescript
authenticate(){
  return this.http.post(
    this.workspace + '/sample-authenticate',
    {},
    this.jsonHeader
  );
}
```

# Step 4: Setting the Access Token <a name="p4"></a>
All authentication in Busywork uses **JWT tokens** to determine whether a user is signed in or not. This also allows you to gate content and query data belonging to this particular user. 

Using JWT tokens requires us to pass this token with every request we make to Busywork. We pass the token in the header of the request. We could set it manually every time we make a request or use a **HttpInterceptor** that can do it for us.

In the `user` folder create a new Typescript file and call it `user.request.interceptor.ts`. This will hold the HttpInterceptor.

```typescript
import {Injectable} from "@angular/core";
import {HttpInterceptor, HttpRequest, HttpHandler} from "@angular/common/http";
import {AuthenticationService} from "./authentication.service";
import {isNullOrUndefined} from "util";

@Injectable()
export class UserRequestInterceptor implements HttpInterceptor {
  constructor(private authService: AuthenticationService){

  }
  
  // interceptor transforms an outgoing request before passing it to the next interceptor
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    // get the users access token using our helper function
    const accessToken = this.authService.getAccessToken();
    
    // in case it isn't set
    if(isNullOrUndefined(accessToken))
      return next.handle(req);
    
    // set the header
    req = req.clone({
      setHeaders: {
        Authorization: "Bearer " + accessToken
      }
    });
    return next.handle(req);
  }
}
```

To use the HttpInterceptor we have to provide it in our app module.

```typescript
@NgModule({
  declarations: [
    AppComponent,
    SignUpComponent,
    SignInComponent,
    ProfileComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    ReactiveFormsModule,
    FormsModule,
    HttpClientModule
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: UserRequestInterceptor,
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
```

# Step 5: Guarding Content <a name="p5"></a>
Implementing user authentication means that we most likely want to guard private content from the public. We will guard certain routes in our app by placing a guard. This guard uses a Busywork function to check if an access token is valid. 

We create the guard using the following command:

`ng g guard user/auth`

In the `auth.guard.ts` file, that you've just created, the class **AuthGuard** implements an interface **CanActivate**. It requires us to return one of the following types:

`Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree`

The response from the Busywork function is a `JSON` object. In order to implement the interface correctly, we need to map the response we get from Busywork.

```typescript
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
  return this.authService.authenticate().pipe(
    map(
      active => {
        return active['status'] == 'success';
      }
    )
  );
}
```

The **canActivate** function is used to determine if a route can be accessed by a user. 

Now we can set up the routes of the app, in **app-routing.module.ts**, and protect the **profile** using our **AuthGuard**.

```typescript
const routes: Routes = [
  {path: '', redirectTo: '/sign-in', pathMatch: 'full'},
  {path: 'sign-in', component: SignInComponent},
  {path: 'sign-up', component: SignUpComponent},
  {path: 'profile', component: ProfileComponent, canActivate: [AuthGuard]}
];
```

# Step 6: Sign Up Component  <a name="p6"></a>
In the sign-up component, we need to create a sign-up form. This is a very simple example, so we only want a username and password. We'll use **Reactive Forms** to build the form validation. This requires us to import the following modules:

`import { ReactiveFormsModule, FormsModule } from "@angular/forms";`

And adding them to the import section of the module declaration in the **app.module.ts** file. 

```typescript
imports: [
  BrowserModule,
  AppRoutingModule,
  ReactiveFormsModule,
  FormsModule,
  HttpClientModule
]
```

In the sign-up component, we will first create a form group with a **username** and **password** field. 

```typescript
form: FormGroup;
constructor(private fb: FormBuilder, private authService: AuthenticationService, private router: Router) {
  this.form = this.fb.group({
    username: new FormControl('', Validators.compose([Validators.required, Validators.minLength(3)])),
    password: new FormControl('', Validators.compose([Validators.required, Validators.minLength(6)]))
  });
}
```

Next, we create a method that is called when the form is submitted. The method will use the **Authentication Service** to send a request to your Busywork API.

```typescript
signUpUser(){
  this.authService.signUp(
    this.form.get('username').value,
    this.form.get('password').value
  ).subscribe(
    (result:any) => {
      if(result['status'] == 'success'){
        this.form.reset();
        this.router.navigate(['sign-in']);
      }
    }
  )
}
```

The HTML part of the component looks like this:

```html
<div class="container">
  <div class="row">
    <div class="col-12">
      <h1>Sign Up</h1>
    </div>
    <div class="col-12">
      <form [formGroup]="form" (ngSubmit)="signUpUser()">
        <div class="form-group">
          <label>Username</label>
          <input type="text" class="form-control" formControlName="username" placeholder="Enter a username" required>
        </div>
        <div class="form-group">
          <label>Password</label>
          <input type="password" class="form-control" formControlName="password" placeholder="Enter a password" required>
        </div>
        <button type="submit" class="btn btn-success">Sign Up</button>
      </form>
    </div>
  </div>
</div>

```

# Step 7: Sign In Component  <a name="p7"></a>
The sign-in component is very similar to the sign-in component. The contents of **sign-in.component.ts** is:

```typescript
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
import {AuthenticationService} from "../authentication.service";

@Component({
  selector: 'app-sign-in',
  templateUrl: './sign-in.component.html',
  styleUrls: ['./sign-in.component.scss']
})
export class SignInComponent implements OnInit {

  form: FormGroup;
  constructor(private fb: FormBuilder, private authService: AuthenticationService) {
    this.form = this.fb.group({
      username: new FormControl('', Validators.required),
      password: new FormControl('', Validators.required)
    });
  }

  ngOnInit() {
  }

  private signInUser(){
    this.authService.signIn(
      this.form.get('username').value,
      this.form.get('password').value
    );
  }

}
```

And **sign-in.component.html**:

```html
<div class="container">
  <div class="row">
    <div class="col-12">
      <h1>Sign In</h1>
    </div>
    <div class="col-12">
      <form [formGroup]="form" (ngSubmit)="signInUser()">
        <div class="form-group">
          <label>Username</label>
          <input type="text" class="form-control" formControlName="username" placeholder="Enter a username" required>
        </div>
        <div class="form-group">
          <label>Password</label>
          <input type="password" class="form-control" formControlName="password" placeholder="Enter a password" required>
        </div>
        <button type="submit" class="btn btn-success">Sign In</button>
      </form>
    </div>
  </div>
</div>
```

# Step 8: Profile <a name="p8"></a>
Now users are able to both sign-up and sign-in, meaning they can access the Profile-page. We haven't collected any information besides the username and password of the user - so we don't have that much to display. But we can allow the user to sign out again. 

In **profile.component.ts** put:

```typescript
import { Component, OnInit } from '@angular/core';
import {AuthenticationService} from "../authentication.service";

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.scss']
})
export class ProfileComponent implements OnInit {

  constructor(private authService: AuthenticationService) { }

  ngOnInit() {
  }
  
  signOutUser(){
    this.authService.signOut();
  }

}

```

And in **profile.component.html**:

```html
<div class="container">
  <div class="row">
    <div class="col-12">
      <h1>You're in!</h1>
      <button type="button" class="btn btn-danger" (click)="signOutUser()">
        Click here to sign-out
      </button>
    </div>
  </div>
</div>
```

# Conclusion <a name="p9"></a>

This concludes this entry-level tutorial on how you can implement user authentication into your app, using Busywork as a backend. In this tutorial, I've shown a minimal example. In Busywork you'll be able to expand the sign-up process to send welcome emails and add a user to your CRM system.

I'm going to post more tutorials on how you can build the backend of your web app using Busywork. Please let me know what topics you would like me to cover.

The tutorial code can be found [in this repository](https://github.com/patrickstolc/angular-8-login).
Check out a demo of the app [here](https://sad-kare-e1112e.netlify.com/sign-up)