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

@pvway/alpha-oas

v15.2.0

Published

This package was build using Angular 15.2.10

Downloads

692

Readme

Alpha OAuth Service (a.k.a. alpha-oas)

This package was build using Angular 17.2.0

It exposes

  • two main services
    • AlphaAosService
    • AlphaAosInterceptor
  • some important classes
    • AlphaPrincipal
    • AlphaUser
    • SessionData
  • and one enum
    • AlphaAuthStatusEnum

AlphaOasService

The AlphaOasService is a service intended for managing user authentication in an Angular 17.2.0 application. It uses the @Injectable decorator to allow for its use throughout the Angular application, and follows the singleton pattern via providedIn: 'root'.

It employs @angular/common/http::HttpClient for calls to HTTP REST API endpoints for managing user sessions and authentication.

Features:

  • Handling user sign in and sign out operations.
  • Managing refreshing of access tokens.
  • Storing access and refresh token details in the session and local storage respectively.
  • Populating and managing Principal details upon user authentication.

Core Methods:

  • init: The method initializes the authentication process and sets the service URLs and delegate methods that handle errors and state changes and returns an Observable.
  • signIn: It accepts username, password and rememberMe as parameters. On successful login, it calls the storeIdentity method.
  • signOut: This method clears session and local storage and updates the principal status to anonymous.
  • authorize: It takes in a http request of type Observable and processes this request. If the access token is expired or is about to expire, it triggers token refresh before handling the http request.
  • editUserInfo: This method is used to update user information in the principal.

Helper Methods:

  • private storeIdentity: This method stores access token, refresh token and user details and updates the principal status.
  • private getMe: This method retrieves user information by making HTTP get request to the given 'getMe' URL.
  • useSignIn, useRefresh, useAuthorize: These methods can be used to override the default signIn, refresh and authorize logic respectively in the service.

Note:

  • The main extension points of the service are methods signIn, signOut, and authorize. They integrate with the actual login form, logout button, and secure HTTP requests respectively.
  • The service leverages includes error handling and optional features like refresh token handling.
  • It provides flexibility to change specific parts of the authentication and authorization process through utility methods: useSignIn, useRefresh and useAuthorize.

Initialization

In order to work as expected, you'll need to

  • inject the OasInterceptor.
  • initialize the service at the very start of your angular application.

Inject the Interceptor

you'll need to inject the OasInterceptor

This can be done into the app.config.ts class

import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { HTTP_INTERCEPTORS } from "@angular/common/http";
import { AlphaOasInterceptor } from "@pvway/alpha-oas";

export const appConfig: ApplicationConfig = {

  providers: [
    provideRouter(routes),
    { provide: HTTP_INTERCEPTORS, useClass: AlphaOasInterceptor, multi: true }
  ]
};

Call the service init method

This is usually done in the onNgInit method of the app.component.

import {Component, OnInit} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {RouterOutlet} from '@angular/router';
import {environment} from "../environments/environment";

import {AlphaTsService} from "@pvway/alpha-ts";
import {AlphaOasService, AlphaPrincipal} from "@pvway/alpha-oas";
import {AlphaLsService} from "@pvway/alpha-ls";
import {AlphaLbsService} from "@pvway/alpha-lbs";

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent implements OnInit {
  pendingInitCount = 2;

  title = 'a17';

  constructor(
    private mHttp: HttpClient,
    private mLs: AlphaLsService,
    private mLbs: AlphaLbsService,
    private mOas: AlphaOasService,
    private mTs: AlphaTsService) {
  }

  ngOnInit() {

    // INITIALIZING OAUTH SERVICE
    // --------------------------
    const getMeUrl = environment.apiHost + '/getMe';
    const refreshUrl = environment.apiHost + '/token';
    const signInUrl = environment.apiHost + '/token';
    const watchOasStateChanges = (principal: AlphaPrincipal) => {
      this.mLbs.publish(principal, 'PRINCIPAL_UPDATED');
    }
    this.mOas.init(mHttp,
      getMeUrl, refreshUrl, signInUrl,
      this.mLs.postErrorLog, watchOasStateChanges)
      .subscribe({
        next: oasStatus => {
          console.log(oasStatus);
          this.pendingInitCount--;
        }
      });

    // INITIALIZING TRANSLATION SERVICE
    // --------------------------------
    const tcUpdateUrl = environment.apiHost + '/getTranslationCacheUpdate';
    this.mTs.init(tcUpdateUrl).subscribe({
      next: tsStatus => {
        console.log(tsStatus);
        this.pendingInitCount--;
      }
    });
  }

}

Let's explain what's happening under the hook.

The init method will actually try to reauthenticate the user and populate the principal using open OAuth so that on completion of the process the principal is set and the user (and all its properties) are set.

It covers the following use cases

Use Case 1: The user was authenticated and refreshes the browser

  • pre-conditions:
    • the user was authenticated and tokens (access token and refresh token) are present in the sessions storage
    • the user refreshes the browser's page
  • primary flow: the OasService will call the getMe end point provided in the init signature. This call reach an authorized end point on the server side that will return user information such as its userId, username and languageCode along with a map of string/string properties such as its first name, last name... any think you want actually.
  • post-conditions:
    • the principal is set with a populated user
    • the principal status is Authenticated

USe Case 2: The browser was closed (i.e. session data was erased)

  • pre-conditions:
    • the user was authenticated in a former session (i.e. a refresh token is present in ths localStorage)
    • in the meantime he closed and reopened the browser so that the oas data in session storage is gone
  • primary low: the OasService will call the refresh end point provided in the init signature. On successful refresh the service then calls the getMe method for populating the principal and the user.
  • post-conditions:
    • the session storage accessToken is set back to new (fresh) values
    • a new refresh token is stored in the localStorage
    • the principal user is set with a populated user
    • the principal status is Authenticated

Use Case 3: The user signed out or this is the first time he connects

  • pre-conditions:
    • the oas data is not present in the sessionStorage
    • the refresh data is not present in the localStorage
  • primary flow: the OasService will set the principal status to anonymous and the user to null
  • post-conditions:
    • the principal user is null
    • the principal status is Anonymous

The init method expects 5 parameters (all optional)

  • getMeUrl: the url of the protected server enc point called for getting back the user profile
  • refreshUrl: the url of the open end point of the identity server (Open OAuth refresh flow)
  • signInUrl: the url of the open end point of the identity server (OPen OAuth Client credentials flow)
  • postErrorLogCallBack: an optional delegate that can log errors to the server
  • watchStatusChangesCallBack: an option delegate that can be used to handle state updates of the principal

In the code here above we are using

  • the postErrorLog method from the alpha-ls component
  • the publish method from the alpha-lbs component

Usage

See here after a small API call that needs to be authorized.

import { Injectable } from '@angular/core';
import {HttpClient, HttpErrorResponse} from "@angular/common/http";
import {catchError, Observable, throwError} from "rxjs";
import {environment} from "../../environments/environment";
import {AlphaLsService} from "@pvway/alpha-ls";
import {AlphaOasService} from "@pvway/alpha-oas";

@Injectable({
  providedIn: 'root'
})
export class DemoApiService {
  
  private mContext = 'DemoApiService';

  constructor(
    private mLs: AlphaLsService,
    private mOas: AlphaOasService,
    private mHttp: HttpClient) { }
  
  // Authenticated method retrieving the main account balance
  getMainAccountBalance(): Observable<number> {
    const url = environment.apiHost + '/Accounts/GetMainAccountBalance';
    const call = this.mHttp.get<number>(url)
      .pipe(
        catchError((error: HttpErrorResponse)=> {
          this.mLs.postErrorLog(this.mContext, 'getMainAccountBalance', 
            JSON.stringify(error));
          return throwError(() => error)
        }));
    return this.mOas.authorize(call);
  }
  
}

As you can see the authorize method is called.

This method will wrap the logic for making sure the http request is authorized using a valid Authorization bearer.

It will also take care of automatically and transparently renewing any expired token using the OpenOAuth refresh flow.

SessionData

This is a small object that is persisted into the sessionStorage.

You can use this object for storing an access token you would get from another IDP (such as when using SSO with a federated OAuth system).

Server side considerations

If you are providing the identity provider server you'll need to make sure it returns the following data to the OasService

export interface IAlphaAuthEnvelop {
  accessToken: string;
  expiresIn: number;
  refreshToken: string;
  user: IAlphaUser;
}

export interface IAlphaUser {
  userId: string;
  username: string;
  languageCode: string;
  properties: Map<string, any>
}
  • the IAlphaAuthEnvelop is a very classical Open OAuth return object that should contain an extra IAlphaUser object
  • the IAlphaUser should contain the userId, the username and the (iso) languageCode for the connected user. It also contains a string/any dictionary where you can pass any data you may need in the client

See also

This component is part of a suite of integrated components