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

aurelia-kis-oidc

v1.9.0

Published

An Aurelia plugin that encapsulates oidc-client-js library.

Downloads

293

Readme

License: MIT npm package codecov

aurelia-kis-oidc

An Aurelia plugin inspired by aurelia-open-id-connect and based on the library oidc-client-js that adapts the OpenID Connect Implicit Client protocol to the Aurelia router in a 'keep it simple' way.

  • After a successful login to the OpenID provider, the access token is automatically attached to the http client, so that further calls to an OAuth2 protected web api will be authenticated.

  • When a web api call is made, the plugin will check the access token validity. If the token has expired, the plugin will try to sign in the user silently in order to get a new access token.

  • If the user has a valid browser session to the OpenID provider, a new access token is retrieved, and the web api is called transparently.

  • If the silent login is not possible the user is prompted to login to the OpenID provider.

  • After the successful login, the user is redirected to his original page.

Features

  • This plugin registers dynamically two routes (signin-oidc and signout-oidc) within your application in order to implement the OpenID Connect Implicit Client protocol.

  • It implements an http interceptor that deals with silent login and bearer token.

  • It is possible to redirect the application on a specific route based on the presence of a specific claim in the user profile (See the redirectsOnClaim configuration property).

  • There is a simulation mode that connect/disconnect the user without interacting with the OpenID provider (See the simulation and simulationUser configuration properties).

Example

A full example written in typescript is available on the following github repo. The example is also available in live here. It is using a Microsoft Azure B2C OpenID/OAuth2 provider and you can login using your GitHub, Microsoft or Google account.

Installation

  1. Install the plugin:

    npm install aurelia-kis-oidc
  2. Call the plugin:

    // in your main.js or main.ts
    export function configure(aurelia) {
      aurelia.use
        .standardConfiguration()
        .plugin(PLATFORM.moduleName('aurelia-kis-oidc'), () => configureOpenidPlugin(aurelia))
  3. Define the plugin configuration method:

    function configureOpenidPlugin(aurelia) {
      return {
        userIdClaimSelector: profile => profile.emails[0],
        reconnectPrompt: loginFunc =>
          iziToast.show({
            title: 'Session expired',
            message: 'Please reconnect',
            buttons: [[`<button>Reconnect</button>`, (instance, toast) => loginFunc(), true]]
          }),
        userManagerSettings: {
          // your oidc-client-js configuration
        }
      }
    }
  4. Connect the router and the httpclient with the plugin:

    // in your app.js or app.ts
    import { inject } from 'aurelia-framework';
    import { HttpClient } from 'aurelia-fetch-client';
    import { OpenidRouting, Oauth2Interceptor } from 'aurelia-kis-oidc';
    
    @inject(OpenidRouting, HttpClient, Oauth2Interceptor)
    export class App {
    
      constructor(openidRouting, client, authInterceptor) {
        this.openidRouting = openidRouting;
        this.configureHttpClient(client, authInterceptor);
      }
    
      configureRouter(configuration, router) {
        ...
        // required
        configuration.options.pushState = true;
        // add dynamically routes for OpenID Connect
        this.openidRouting.configureRouter(configuration);
        ...
      }
    
      configureHttpClient(client, authInterceptor) {
        return client.configure(config => {
          config
            .withDefaults({
              headers: {
                'Access-Control-Allow-Credentials': 'true',
                'Accept': 'application/json'
              },
              credentials: 'include',
              mode: 'cors'
            })
            .rejectErrorResponses()
            .withInterceptor(authInterceptor)
        });
      }

User interface

This plugin does not come with any user interface element but it provides a Connection class that encapsulates the OpenID Connect user connection. Just inject the Connection class within your viewmodel and bind your html elements to it.

//login.js
import { inject } from 'aurelia-framework';
import { Connection } from 'aurelia-kis-oidc';

@inject(Connection)
export class Login {
  constructor(connection) {
    this.connection = connection;
  }
<!-- login.html -->
<template>
  <!-- a login button -->
  <button click.trigger="connection.loginUser()">
    Login
  </button>
  <!-- a conditional lougout link with user name -->
  <a if.bind="connection.isUserLoggedIn" click.trigger="connection.logoutUser()">
    Logout ${connection.userId}
  </a>
</template>

You can change the claim that is used to represent the identifier of the user (property userId): see the userIdClaimSelector configuration property.

You can also change the user prompt interface when the session has expired: see the reconnectPrompt configuration property.

Configuration options

You can define specific options in the configuration returned by the configureOpenidPlugin function.

userIdClaimSelector

Function that defines the profile claim used as user identifier.

Example:

/**
* Defines the profile claim used as user identifier.
* @param {Object} profile - the user profile containing claims
* @return {string} the user identifier
*/
const userIdClaimSelector = profile => profile.emails[0];

If you do not define this option, the default claim used is the name claim.

reconnectPrompt

Function that defines the user prompt to reconnect the session when it is expired.

By default, it displays the native browser prompt.

Here's an example with the iziToast component:

/**
* Implements the reconnect prompt with izitoast component.
* @param {I18N} i18n -  the translation plugin
* @return {function} the function called to reconnect the session
*/
const reconnectPrompt = loginFunc => {
 iziToast.show({
   theme: 'dark',
   title: 'Session expired!',
   message: 'Please reconnect...',
   buttons: [[`<button>Reconnect</button>`, (instance, toast) => loginFunc(), true]]
 });
};

loginRequiredSelector

To determine that the silent login is not possible the OpenID provider will return an error. The plugin must handle the correct error code in order to show the reconnect prompt. The loginRequiredSelector function defines this code analysis. The default function is the following (which is what Microsoft Azure B2C authentication currently returns when silent login is no more available):

error => error.error === 'interaction_required';

You can customize it. For instance this is the function I use for an application authenticated by Azure Active Directory (and it should be the same for Azure B2B authentication):

error => error.error === 'login_required';

redirectsOnClaim

Sometimes you want to redirect the router to a specific route after the login when a special claim is present.

For instance, with Azure B2C there is a special claim when the user has just created his account.

You can use the redirectsOnClaim function for that.

Example:

/**
* Defines the redirect route based on specific profile claims.
* @param {Object} profile - the user profile containing claims
* @return {string} the route name or undefined
*/
const redirectsOnClaim = profile => {
  // redirect newly created users to the settings view
  if (profile?.newUser) return 'settings';
};

onError

Sometimes the oicd provider may return an error during the response callback.

You can use the onError callback to retrieve the error.

Example:

const onError = error => {
  // for instance for errors returned by Azure AD
  console.log(error.error_description);
};

userManagerSettings

This object is the exact configuration object of the openid-client-js library.

See oidc-client-js wiki.

The redirect_uri must be: https://whatever_your_aurelia_app_url/signin-oidc

If you specify post_logout_redirect_uri it should be: https://whatever_your_aurelia_app_url/signout-oidc

simulation

This boolean is for development purpose only. It enables to bypass the OpenID provider dialog and to connect virtually the user.

When you call the loginUser method of the Connection class the user is automatically connected as the default following user:

{
  profile: { name: 'Test User' },
  expired: false,
  access_token: '0123456789'
}

You can define your own user object: see the simulationUser configuration property.

When you call logoutUser of the Connection class the user is automatically disconnected.

Of course as the access token is fake you won't be able to call a protected web api.

simulationUser

This object enables you to define a custom connected user that should fit your needs.

Example:

simulationUser: {
      profile: { name: 'J.DOE', emails: ['[email protected]']},
      expired: false,
      access_token: '0123456789'
    },

Project documentation

The project documentation has been generated with jsdoc and the kis-jsdoc-plugin.

The table of content is here.