v0.8

Auth

class Auth → file: core/lib/Auth.js

Authentication with the JWT token and cookie.

Instance

The auth instance is created by new Auth(authOpts).

Auth Properties

Property Description Type Default
authOpts The auth options (see table below). object {...}
cookie The lib/Cookie class instance. object {...}
httpClient The HTTPClient class instance. object {...}
jwtToken JWT token received after succesful login, for example: 'JWT aWqwada...' string
loggedUser The user object. Required fields: {username:string, password:string, role:string}. The role can be 'admin' for example. object {}

authOpts

Property Description Type Default
apiLogin API login url, for example: http://127.0.0.1:8001/users/login string
afterGoodLogin redirect after succesful login, for example '/{loggedUserRole}/dashboard' string
afterBadLogin redirect after unsuccesful login, for example '/login' string
afterLogout URL after logout() method is used, for example '/login' string

NOTICE: The parameter afterGoodLogin can contain {loggedUserRole} which will be replaced with the user role. For example /{loggedUserRole}/dashboard will be resolved to /admin/dashboard if the user's role is 'admin'.

Methods

Use this methods for the authentication and to guard specific routes from unauthorised access.
Use app.auth($auth) to inject $auth in the controller property this.$auth, where $auth is Auth class instance.

async login(creds) :Promise<object>

Call API's URL defined by authOpts.apiLogin parameter.
The returned value is the API response i.e. JS object:
On succesful login two cookies are created:
a) auth_jwtToken with value for example: 'JWT aWqra...'
b) auth_loggedUser with value of the user object which is returned by the API
    ARGUMENTS:
  • creds :object - credentials object sent as body to the API: {username :string, password :string}

async logout(ms) :Promise<void>

Logout by deleting auth_jwtToken and auth_loggedUser cookies and redirect to afterLogout URL.
    ARGUMENTS:
  • ms :number - the logout delay after the method logout is called

getLoggedUserInfo(ms) :object

Get logged user info returned from the API and saved in the auth_loggedUser cookie.

getJWTtoken() :string

Get JWT token returned from the API and saved in the auth_jwtToken cookie.



Auth Guards

There are also other methods which shouldn't be used in the controller but as the route guard options (route middleware functions).

- autoLogin() --Checks if user is logged and if yes do auto login e.g. redirect to afterGoodLogin URL.
Use route guard option: ['when' '/login' 'LoginCtrl', {autoLogin: true}]

- isLogged() --Checks if user is logged and if not redirect to afterBadLogin URL.
Use route guard option: ['when' '/admin/product/:id' 'AdminProductCtrl', {isLogged: true, hasRole: true}]

- hasRole() --Checks if logged user has required role: 'admin', 'customer'...etc which corresponds to the URL. For example role "admin" must have URL starts with /admin/.
Use route guard option: ['when' '/admin/product/:id' 'AdminProductCtrl', {isLogged: true, hasRole: true}]




EXAMPLE:
First define lib/auth.js
import { corelib } from '@mikosoft/dodo';
const env = import .meta.env;

const baseURL = env.DODO_API_baseURL;
const authOpts = {
  apiLogin: `${baseURL}/panel/users/login`,
  afterGoodLogin: '/{loggedUserRole}/dashboard', // redirect after succesful login:
  afterBadLogin: '/',  // redirect after unsuccesful login
  afterLogout: '/'     // URL after logout
};
const auth = new corelib.Auth(authOpts);

export default auth;

After that edit app.js and inject auth.
import auth from '/lib/auth.js';
import $routes from '/routes.js';

const app = new App('myApp');
app
  .auth(auth)
  .httpClient($httpClient)
  .fridge('wsLib', wsLib)
  .preflight($preflight)
  .postflight($postflight)
  .debug($debugOpts);

app
  .routes($routes)
  .listen();

And finally add login() method in the LoginCtrl.js controller
LoginCtrl.js
---------------------------
export class LoginCtrl extends Controller {
  async tryLogin() {
    try {
      const username = this.username;
      const password = this.password;
      await this.$auth.login({ username, password });
    } catch (err) {
      popups.notify(err.message, 'inverse');
      console.error(err);
    }
  }
}

views/pages/login.html
---------------------------
<form>
  username: <input type="text" name="username" dd-set="username">
  password: <input type="text" name="password" dd-set="password">
  <button dd-click="tryLogin()">Login</button>
</form>

Don't forget to use auth grads in route definitions i.e. routes.js file:
import LoginCtrl from '/controllers/LoginCtrl.js';
import DashboardCtrl from '/controllers/DashboardCtrl.js';
import auth from '/lib/auth.js';

// auth gurads
const autoLogin = auth.autoLogin.bind(auth);
const isLogged = auth.isLogged.bind(auth);
const hasRole = auth.hasRole.bind(auth);

const $routes = [
  ['when', '/', LoginCtrl, { authGuards: [autoLogin] }],
  ['when', '/developer/dashboard', DeveloperDashboardCtrl, { authGuards: [isLogged, hasRole] }],
];

export default $routes;
The server API response after succesful login;
{
  "success": true,
  "message": "Login was successful. JWT is generated and you can use it in API request header. Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYwOWY3NGI5Y2Y0NDE5MGEyZDIzN2E2YiIsInVzZXJuYW1lIjoiZGV2YSIsImlhdCI6MTY5MDAyMDE0Mn0.uqGjSwq8Nox-BeNEm-nNi_4Ab03ThOQTlPd3-VBu3QM",
  "jwtToken": "JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkqYVCJ9.eyJpZCI6IjYwOWY3NGI5Y2Y0NDE5MGEyZDIzN2E2YiIsInVHHXJuYW1lIjoiZGV2YSIsImlhdCI6MTY5MDAyMDE0Mn0.uqGjSwq8Nox-BeNEm-nNi_4Ab03ThOQTlPd3-VBu3QM",
  "loggedUser": {
      "role": "developer",
      "is_active": true,
      "login_counter": 52,
      "connected": false,
      "_id": "609f74b9cf44190a2d237a6b",
      "first_name": "Deva",
      "last_name": "Dev",
      "address": "Roki street 33",
      "city": "NY",
      "country": "USA",
      "email": "deva@test.com",
      "website": "www.deva.com",
      "phone": "+1 111222333",
      "misc": null,
      "username": "deva",
      "password": "--removed--",
      "created_at": "2021-05-15T07:14:01.280Z",
      "updated_at": "2023-07-20T09:24:24.180Z",
      "__v": 0,
      "login_last": "2023-07-20T09:12:53.118Z",
      "login_last_ip": "93.139.0.224",
      "ip": "",
      "port": null,
      "socketId": ""
  }
}
}


Stackblitz Examples

  • Auth - test login, logout and route gurads: autoLogin, isLogged, hasRole