npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ngboost-auth

v2.0.1

Published

Angular authentication service with Json Web Token (JWT).

Downloads

17

Readme

ngboost-auth

Angular module for Json Web Token (JWT) authentication. The module methods are used with Angular router.

Installation

$ npm install --save ngboost-auth

Features

  • AuthService - use in component: login, logout, getLoggedUserInfo, getJWTtoken
  • JwtTokenInterceptor - intercept every request of the httpClient and add header Authorization: JWT ...
  • IsLoggedService route guard - check if the user is logged succesfully, if not return to afterBadLogin
  • HasRoleService route guard - check if the logged user has valid role (admin,customer,...), if not return to afterBadLogin
  • AutologinService route guard - if the user is logged redirect from /login route to afterGoodLogin route

AuthService Methods

login(creds: Credentials): Observable

Login with const creds = {username: 'xxxx', password: 'yyyy'} and redirect to URL defined by auth_urls.afterGoodLogin.

Required 'creds' properties are:

interface Credentials {
  username: string;
  password: string;
}

logout(): void

Logout and remove cookies.

getLoggedUserInfo(): LoggedUser

Get logged user info. This object is returned by API and stored into cookie auth_loggedUser. Set auth_jwtToken and auth_loggedUser cookies.

Required user object properties are:

interface LoggedUser {
  first_name: string;
  last_name: string;
  address?: string;
  city?: string;
  country?: string;

  phone?: string;
  email: string;
  website?: string;

  username: string;
  password?: string;

  role: string;
  is_active?: boolean;
}

so API response should return those fields.

getJWTtoken(): string

Take JWT token from 'auth_jwtToken' cookie. This token is fetched from API and stored in 'auth_jwtToken' cookie. Remove auth_jwtToken and auth_loggedUser ccokies.

Integration

1. app.module.ts

import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { NgboostAuthModule } from 'ngboost-auth';
import { AppRoutingModule } from './app-routing.module';

const api_base_url = 'http://localhost:4444';

const auth_urls = {
  apiLoginUrl: `${api_base_url}/users/login`,
  afterGoodLogin: '/{loggedUserRole}/dashboard', // {loggedUserRole} -> 'admin' | 'customer'
  afterBadLogin: '/login',
  afterLogout: '/login'
};

@NgModule({
  declarations: [],
  imports: [ AppRoutingModule, NgboostAuthModule, HttpClientModule ],
  providers: [
     // required injections for ngboost-auth
    { provide: 'AUTH_URLS', useValue: AUTH_URLS }, // send AUTH_URLS to ngboost-auth
    { provide: HTTP_INTERCEPTORS, useClass: JwtTokenInterceptor, multi: true }, // take JwtTokenInterceptor from ngboost-auth and send to HttpClientModule
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

Notice: {loggedUserRole} is a placeholder which is replaced with user's role: admin, customer, ...etc. User's role have to be returned by API after succesful login.

2. app-routing.module.ts

// modules
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

// components
import { HomeComponent } from './pages/home/home.component';
import { LoginComponent } from './pages/login/login.component';
import { AdminComponent } from './pages/admin/admin.component';
import { CustomerComponent } from './pages/customer/customer.component';
import { NotfoundComponent } from './pages/notfound/notfound.component';

// services
import { IsLoggedService, HasRoleService, AutologinService } from 'ngboost-auth';

// routes
const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'login', component: LoginComponent, canActivate: [AutologinService] },
  { path: 'admin', component: AdminComponent, canActivate: [IsLoggedService, HasRoleService] },
  { path: 'customer', component: CustomerComponent, canActivate: [IsLoggedService, HasRoleService] },
  { path: '404', component: NotfoundComponent },
  { path: '**', redirectTo: '/404' }
];


@NgModule({
  imports: [ RouterModule.forRoot(routes) ],
  providers: [IsLoggedService, HasRoleService, AutologinService],
  exports: [ RouterModule ],
  declarations: [
    HomeComponent,
    LoginComponent,
    AdminComponent,
    CustomerComponent,
    NotfoundComponent
  ]
})

export class AppRoutingModule {}

Backend API response

In order to work properly this ng module requires this kind of JSON response from the API server:

{
    "success": true,
    "message": "Login was successful. JWT is generated and you can use it in API request header. Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVhZjdmYTZmMjlmOWJlMTg1MmRkNjMyZSIsInVzZXJuYW1lIjoiYWRtaW4iLCJpYXQiOjE1Mjc5MzYxNjR9.QI78esEzZkxpkuMhWGqPASGvRvrti1GNWM7ozxnvyfU",
    "jwtToken": "JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVhZjdmYTZmMjlmOWJlMTg1MmRkNjMyZSIsInVzZXJuYW1lIjoiYWRtaW4iLCJpYXQiOjE1Mjc5MzYxNjR9.QI78esEzZkxpkuMhWGqPASGvRvrti1GNWM7ozxnvyfU",
    "loggedUser": {
        "role": "admin",
        "is_active": true,
        "_id": "5af7fa6f29f9be1852dd632e",
        "first_name": "Marko",
        "last_name": "Adminić",
        "address": "Radića 23",
        "city": "Osijek",
        "country": "Croatia",
        "phone": "+385-93-2111-222",
        "email": "[email protected]",
        "website": "www.uniapi.org",
        "username": "admin",
        "created_at": "2018-05-13T08:42:23.363Z",
        "updated_at": "2018-06-02T10:42:44.175Z",
        "__v": 0,
        "jwt_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVhZjdmYTZmMjlmOWJlMTg1MmRkNjMyZSIsInVzZXJuYW1lIjoiYWRtaW4iLCJpYXQiOjE1Mjc5MzYxNjR9.QI78esEzZkxpkuMhWGqPASGvRvrti1GNWM7ozxnvyfU"
    }
}

AuthService Method Examples

login({username: , password: })

/pages/login/login.component.html

<form id="login-form" action="#" method="POST" novalidate="" [formGroup]="loginFG">
    <div class="form-group">
        <label for="username">Username</label>
        <input type="text" class="form-control underlined" placeholder="Your username" required formControlName="username"> </div>
    <div class="form-group">
        <label for="password">Password</label>
        <input type="password" class="form-control underlined" placeholder="Your password" required formControlName="password"> </div>
    <div class="form-group">
        <button type="button" class="btn btn-block btn-primary" (click)="login()">Login</button>
    </div>
    <div>
        <p class="alert alert-warning" *ngIf="!!err && !!err.message">{{err.message}}</p>
    </div>
</form>

/pages/login/login.component.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { AuthService } from 'ngboost-auth';


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

  loginFG: FormGroup;
  err: Error;

  constructor(private fb: FormBuilder, private authService: AuthService) { }

  ngOnInit() {
    this.loginFG = this.fb.group({
      username: '',
      password: ''
    });
  }


  login() {
    const creds = this.loginFG.value; // {username: , password: }
    this.authService.login(creds)
      .subscribe({
        next: (apiResp: any) => {
          const jwtToken = this.authService.getJWTtoken();
          console.info('LOGGED USER:: ', apiResp.loggedUser, ' jwtToken=', jwtToken);
          this.msg = apiResp.msg;
        },
        error: err => {
          this.errMsg = err.error.message;
          setTimeout(() => { this.errMsg = ''; }, 2100);
          console.error('ERROR: ', err);
        }
      });
  }

}

logout()

/pages/admin/admin.component.html

<a class="dropdown-item" [routerLink]="" (click)="logout()"><i class="fa fa-power-off icon"></i> Logout </a>

/pages/admin/admin.component.ts

import { Component, OnInit } from '@angular/core';
import { AuthService } from 'ngboost-auth';

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

  loggedUser: any;

  constructor(private authService: AuthService) {
    this.loggedUser = authService.getLoggedUserInfo();
  }

  ngOnInit() {
  }

  logout() {
    console.log('LOGOUT:: ');
    this.authService.logout();
  }

}

Protections

A] Route Guards

To protect angular routes from unauthorized access this service uses canActivate route guards:

  • IsLoggedService check if user is logged with valid username:password.
  • HasRoleService check if user has appropriate role, e.g. role must be contained in URL string, for example: /admin/dashboard is valid for 'admin' role but /customer/dashboard is not valid for 'admin' role. This guard must be applied after IsLoggedService guard.
  • AutologinService check if user is already logged. If yes then automatically redirect to URL defined by auth_urls.afterGoodLogin. This guard should be applied only on login page e.g. /login angular route.

B] API HTTP Request protections

To protect each API request use JWT Token from 'auth_jwtToken' cookie and use it in HTTP header 'Authorization: JWT ' as HTTP interceptor for each API request.

Licence

Created by Saša Mikodanić under MIT licence.