2.0.2 • Published 5 years ago

@hgmap/lbext-auth v2.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
5 years ago

@hgmap/lbext-auth

A Loopback 4 authentication out of the box. Include DataSources,Models,Repositories artifacts.

Overview

This component contains datasources,models,repositories for speed up your start with an authentication of Loopback 4 application.

Fast Start

  1. lb4 app-test
  2. cd app-test/ && npm install --save @hgmap/lbext-auth
  3. cp node_modules/\@hgmap/lbext-auth/examples/application.ts src/
  4. cp node_modules/\@hgmap/lbext-auth/examples/sequence.ts src/
  5. cp node_modules/\@hgmap/lbext-auth/examples/defaultUsers.json ./ this database contains all users with password '12345678' (e.g. { login: 'mpavlov02@email.me', password: '12345678' })
  6. npm run start

Application class name is AppTestApplication by default. You can rename it.

Usage:

  1. npm install --save @hgmap/lbext-auth

  2. Edit application.ts by adding import from this component and activate it by calling app.component() method of the application and add component (@hgmap/lbext-auth) configuration.

You can use default artifacts (controllers,models,datasources,repositories) if you don't need any specific features.

...
    options.lbextAuth = {
      defaultArtifacts: {
        repositories: {
          repoUser: true  // use UserRepository from component; if false then use copy or your own from <projDir>/src/repositories/<UserRepository>.ts
        },
        controllers: {
          auth: true,     // use AuthController from component; if false then use copy or your own from <projDir>/src/controllers/<AuthController>.ts
          user: true,     // use UserController from component; if false then use copy or your own from <projDir>/src/controllers/<UserController>.ts
        },
        datasources: {
          dataUser: true, // use UserDataSource from component; if false then use copy or your own from <projDir>/src/datasources/<UserDataSource>.ts
          // if it's true, you can also reconfigure datasource by it's config only in the UserServiceBindings.DS_CFG variable
        },
      },
    };
...

Also you can copy needed files to your project source directory from component sources node_modules/@hgmap/lbext-auth/src/default-artifacts/<needed part>

You may want to following some scenarios:

  • overwrite config of default datasource (use another connector or destination path of memory data file)
  • create your own (or copy default ones to application source directory) datasource(s) and set defaultArtifacts.datasources.dataUser = false
  • create your own (or copy default ones to application source directory) repositories and set defaultArtifacts.repositories.repoUser = false and create your own (or copy default ones to application source directory) model(s) and it's relations
  • create your own (or copy default ones to application source directory) controller(s) and set defaultArtifacts.controllers.<auth or/and user> = false
  1. Edit sequence.ts by adding import from this component and insert one line of code that calling of .AUTH_ACTION from AuthenticationBindings imported.

User database is in the process.cwd()+'/defaultUsers.json' by default. But you can change it by configure (see #1)

That's all

All you need is @authenticate('jwt') on every method to be authenticated !

src/sequence.ts

...

++ import {
++   AuthenticateFn,
++   AuthenticationBindings,
++ } from '@hgmap/lbext-auth';

...

export class MySequence implements SequenceHandler {
  constructor(

...

++  @inject(AuthenticationBindings.AUTH_ACTION) public authRequest: AuthenticateFn,
  ) {}

  async handle(context: RequestContext) {
    try {
      const {request, response} = context;
      const route = this.findRoute(request);

++    await this.authRequest(request);

      const args = await this.parseParams(request, route);
      const result = await this.invoke(route, args);
      this.send(response, result);
    } catch (err) {
      this.reject(context, err);
    }
  }
}

src/application.ts

...

++ import {
++   AuthComponent, TokenServiceBindings, PasswordServiceBindings, UserServiceBindings,
++ } from '@hgmap/lbext-auth';

export class ApiCoreApplication extends BootMixin(
  ServiceMixin(RepositoryMixin(RestApplication)),
) {
  constructor(options: ApplicationConfig = {}) {
    super(options);

	...


    // component lbext-auth config

++    options.lbextAuth = {
++      defaultArtifacts: {
++        repositories: {
++          repoUser: true  // use UserRepository from component; if false then use copy or your own from <projDir>/src/repositories/<UserRepository>.ts
++        },
++        controllers: {
++          auth: true,     // use AuthController from component; if false then use copy or your own from <projDir>/src/controllers/<AuthController>.ts
++          user: true,     // use UserController from component; if false then use copy or your own from <projDir>/src/controllers/<UserController>.ts
++        },
++        datasources: {
++          dataUser: true, // use UserDataSource from component; if false then use copy or your own from <projDir>/src/datasources/<UserDataSource>.ts
          // if it's true, you can also reconfigure datasource by it's config only in the UserServiceBindings.DS_CFG variable
++        },
++      },
++    };
++    this.component(AuthComponent);
/**
    configure TokenService (for JWT authentication) and PasswordService (hash settings)
*/
    // default: "ZDUwYTc3OGM4Y2NjOTUwODQ0NTMyNWU3MWJlZmJjOTI3ZWUwNzRmMSAgLQo="
++    this.bind(TokenServiceBindings.SECRET).to('AS SECRET YOU CAN USE RS256 ALG WITH CERTIFICATE');
/**
    you can create and use certificate:
      const private_key = fs.readFileSync('path/to/cert/directory/private.key','utf8'); - for generateToken - as your secret
      const public_key = fs.readFileSync('path/to/cert/directory/public.key','utf8'); - for verifyToken - you can use it on many other servers...
*/
    // default: "LoopbackApp"
++    this.bind(TokenServiceBindings.ISSUER).to('Issuer');
    // default: "Loopback"
++    this.bind(TokenServiceBindings.AUDIENCE).to('Audience');
    // default: "600" NOTE: string
++    this.bind(TokenServiceBindings.EXPIRES_IN).to('600');


    // default: "MzQ5MjBhZGQyYTZhZmJkNzJiZmNlNDc0NGU0OWVhMTg1NDk0YzM4YiAgLQo="
++    this.bind(PasswordServiceBindings.SALT).to('SALT ITS NOT REQUIRED');
    // default: 64 bytes - hash length
++    this.bind(PasswordServiceBindings.LENGTH).to('64');

/**
    if defaultArtifacts.datasources.dataUser is true (also any of available datasources) then you can reconfigure default UserDataSource (overwrite config)
    by binding of datasource config to UserServiceBindings.DS_CFG. See below

 ---
    this.bind(UserServiceBindings.DS_CFG).to({
        "name": "dbusers",
        "connector": "memory",
        "localStorage": "",
        "file": process.cwd()+'/db-users.json',
    });
 ---

    or use your favourite connector...




    if you didn't define datasource User that use the default one from component
    then you need uncomment lines below and copy defaults/create your own datasource.
    As below:

 ---
    this.bind(UserServiceBindings.DS).toClass(UserDataSource);
 ---




    if you didn't define defaultArtifacts.repositories or set defaultArtifacts.repositories.repoUser to false
    then you need copy default to your application src/repositories directory or create your own by lb4/manual
    And bind it to UserServiceBindings.REPO_USER as you can see below:

 ---
    this.bind(UserServiceBindings.REPO_USER).toClass(UserRepository);
 ---

    NOTE: you also need to create User model and UserRelations ...
*/

  }
}

Default login in API explorer (swagger)

Swagger user interface of API explorer is on localhost:3000/explorer by default To be logged in you need go through some steps:

  1. Create the first user in the top application directory (the same level of src/ and dist/ directories) in the file defaultUsers.json or in your database if you use your own...
{
  "ids": {
    "User": 2
  },
  "models": {
    "User": {
      "1": "{\"id\":1,\"firstname\":\"John\",\"lastname\":\"Travolta\",\"username\":\"JT100\",\"email\":\"whatever@email.me\",\"password\":\"rDFsmb5END6nX7denegFLEed7UA3YwEBGQvqNjrdnT9Jk1OrsCAGVM4kh16xt5DCrsxxpT4YF6t3tNSl7hcFSQ==\"}"
    }
  }
}

copy and paste above code to this file. Credentials of this new user is login: whatever@email.me and password: 12345678.

  1. go to localhost:3000 and press on the Authorize button step0

  2. enter login and password to basic authentication part. step1 step2

  3. press on to /login/basic method, then press on to try it out and press execute. Alternatively, you can insert credentials to request body data of the /login/json method... This actions returns token that needed to authenticate for all other methods.

  • press method step3
  • press try it out step4
  • press execute step5
  • got token step6
  1. This token need to be pasted to Authorization modal form - JWT part. (press Authorize button on the top of the page) step7

Now, You can do all of actions following 10 minutes (600 sec by default). Enjoy )