Authenticating with OpenID Connect (OIDC) in TypeScript

Connecting to OpenID Connect (OIDC) and OAuth2 protocol support for browser-based applications is something that occurs more frequently. One well-known example is to use Google Auth to have your user authenticate instead of having to handle a custom password approach to your web application. My case was that I needed to authenticate against a private federated system.

Before going into detail, the project I am building is using React, Redux and TypeScript. In this article, I’ll bring an open-source library named oicd-client-js. It’s open source on Github and has a NPM package available.

First, you need to install the library, and second, you do not need any types for TypeScript — the library contains the definition file. This is great because it means that it will be updated more frequently.

npm install oidc-client --save

A word of caution, the library’s documentation is very thin. While having some samples, most of them don’t explain which settings are required to have it work. In this article, I won’t call any function to log out else than flushing on the client side the local storage. If you look at the library, there are potential functions that could be called — it never worked for me.

The first thing you need is to have your React component dispatching two events. One would be to log in, the other one to log out. I opted to have the dispatcher calling an action creator that looks like this:

export function onAppLogin(): ThunkAction<void, AppRootReducer, {}> {
    return (dispatch: Dispatch<Actions<void>>, getState: () => AppRootReducer, extra: {}) => {
        dispatch(actionAppLoginStarted()); 
        Auth.getInstance().login(); 
    };
}

export function onAppLogout(): ThunkAction<void, AppRootReducer, {}> {
    return (dispatch: Dispatch<Actions<void>>, getState: () => AppRootReducer, extra: {}) => {
        Auth.getInstance().logout().then(() => {
            dispatch(actionAppLogout());
        });
    };
}

Both are actually calling the singleton Auth which contains a login and logout function. The Auth class is a singleton because it will be used in these two functions but also in a Redux’s Middleware later. The way it works is that when we will call the login function that this one will invoke the third-party library and will receive from the server a URL that the client will need to navigate to. This is required in case the user is not authenticated yet with the OpenId server. When the navigation is done, the server will callback the application. This is where the Redux’s Middleware will be interesting. Since Redux’s Middleware listen to every action, if we have a custom middleware we are able to listen if we expect to do any work. This is why we will use a temporary entry inside a local storage to set a flag saying if we need to do any login or logout work. In the case of login, we will fetch the user’s information and dispatch an action that will store the access token and user’s name, email, etc into our store. For the logout, same thing. The middleware will remove the user from the store once this one is getting dismissed.

import OIDC, { UserManagerSettings } from "oidc-client";

export class Auth {

    private static OidcSettings: UserManagerSettings = {
        automaticSilentRenew: true,
        authority: "https://meechum.netflix.com",
        client_id: "cdnadminpartner",
        redirect_uri: window.location.protocol + "//" + window.location.host + "/index",
        post_logout_redirect_uri: window.location.protocol + "//" + window.location.host + "/index",
        silent_redirect_uri: window.location.protocol + "//" + window.location.host + "/index",
        response_type: "code token id_token",
        scope: "openid profile",
        loadUserInfo: true,
        userStore: new OIDC.WebStorageStateStore({ store: window.localStorage })
    };


    private static instance: Auth; 
    private static readonly KEY_FOLLOW = "my_app_follow_action_required";
    private static readonly KEY_PROCESS_LOGIN = "login";
    private static readonly KEY_PROCESS_LOGOUT = "logout";

    private user: OIDC.UserManager;

    public static getInstance(): Auth {
        if (Auth.instance === undefined) {
            Auth.instance = new Auth();
        }
        return Auth.instance;
    }


    public process(): Promise<UserFromMeechum | undefined> {
        if (this.mustFollowAuthLogin()) {
            return this.processSigninResponse()
                .then((response) => {
                    return response;
                });
        } else if (this.mustFollowAuthLogout()) {
            return this.processSignoutResponse()
                .then((response) => {
                    return undefined;
                });
        } else {
            return this.getUser();
        }
    }

    public getUser(): Promise<any | null> {
        return this.user.getUser();
    }


    public login(): void {
        this.user.createSigninRequest()
            .then((response) => {
                this.getStorage().setItem(Auth.KEY_FOLLOW, Auth.KEY_PROCESS_LOGIN);
                window.location.href = response.url;
            });
    }

    public logout(): Promise<void> {
        return this.user
            .removeUser();
    }


    private constructor(private storage: StorageType = StorageType.LocalStorage) {
        const level = Log.getOptions().logMaxLevelOfTracing;
        const verboseLevel = TraceType.Verbose;
        if (level >= verboseLevel) {
            OIDC.Log.logger = console;
            OIDC.Log.level = OIDC.Log.DEBUG;
        }
        this.user = new OIDC.UserManager(Auth.OidcSettings);
    }
    private processSigninResponse(): Promise<UserFromMeechum> {
        this.getStorage().removeItem(Auth.KEY_FOLLOW);
        return this.user.signinRedirectCallback();
    }

    private processSignoutResponse(): Promise<null> {
        this.getStorage().removeItem(Auth.KEY_FOLLOW); 
        return this.user
            .processSignoutResponse() 
            .then((response) => {
                return null;
            });

    }

    private mustFollowAuthLogin(): boolean {
        return window.localStorage.getItem(Auth.KEY_FOLLOW) === Auth.KEY_PROCESS_LOGIN;
    }
    private mustFollowAuthLogout(): boolean {
        return window.localStorage.getItem(Auth.KEY_FOLLOW) === Auth.KEY_PROCESS_LOGOUT;
    }
}

The middleware is getting hammered, like any middleware. However, the only task it does is to check for the localstorage to see if a flag for action is required or not. If not, it calls the next middleware. It’s pretty fast. Otherwise, it goes the final step for the authentication.

Further work could be done in term of logout by calling “createSignoutRequest” for instance. I have created a Github issue and hope to get an answer by the time this article is published. At the moment, the problem is that the library response with “No end session endpoint url returned” which is awkward because if we look at the source code, the endpoint is optional. I do not set this one (and haven’t found where it can be set). Nevertheless, the code of this article works well and you will have your token id and access id as well as all the user information.

Capturing Performance in a React and Redux Web Application

Recently, I started working a project and wanted to gather information in regard to performance. I wanted to have insight about where code could be improved over time. This means that I need to have entry points where I can collect metrics and send them to the server. In this article, I won’t discuss the detail of how to send the information, but more about where to set these markers.

Before anything, let’s clarify the situation. This is a React application, that uses Redux as the way to manipulate the data flow. The application has container components that are connecting to the store through the “connect” React-Redux function. Presentation components will delegate back to the container component. Once an action occurs, the “mapDispatchToProps” of the corresponding container component calls the dispatch method The exact flow that React dispatch a call to the action creator. This latter can do some business logic and Ajax call to finally dispatch an action that will be intercepted reducers. Between the beginning of the call to the reducer and the end, middlewares can act upon the state. Finally, the “mapStateToProps” of the connected component is called and change the state of the component which will call the shouldComponentUpdate, the render and the componentDidUpdate.

I’ve seen many places on the Internet that were placing performance markers in a middleware. I can understand the appealing reason of being easily injectable, but that doesn’t cover the whole flow as I just described.

The confirm what my hypothesis of having to start performance log right before the dispatch and the performance log to stop at the update method, let’s do an experience with some console.log in 6 different places. The first one right before “dispatching” to the action creator. One in the first line of the action creator, a third one in the render method of the component, and a fourth one in the componentDidUpdate. Finally, two console.log in a basic middleware invokes the console before and after the action.

The order is:

1- Dispatch
2- ActionCreator (first line)
3-Middleware before action
4-Middleware after action
5-Component Render
6-Component componentDidUpdate

That being established, calling any kind of stop marker at a middleware level is preamptive. This is even truer if you are using Perf.start() and Perf.stop() at the Middleware level.

How to Create a Typed Redux Middleware in TypeScript

A quick search on Internet will provide many JavaScript implementations of Redux middleware which all look alike at first look: confusing with the three fat arrows. Here is an illustration of what I mean

const loggerMiddleware = store => next => action => {
  console.log("Before");
  const result = next(action)
  console.log("After"); // Can use: store.getState()
  return result
}

Not knowing the type of what is between the arrow, for the store, next or action is very confusing. This is where type can get help to get your head around what is going on. The following code is the same exact code using Microsoft TypeScript.

import { Middleware, MiddlewareAPI, Dispatch, Action } from "redux";
export const loggerMiddleware: Middleware = <S>(api: MiddlewareAPI<S>) =>
    (next: Dispatch<S>) =>
        <A extends Action>(action: A): A => {
            console.log("Before");
            const result = next(action);
            console.log("After"); // Can use: api.getState()
            return result;
        };

The first line describes that the middleware is typed of “S” which will be the “state” that the middleware can access. If you are using Redux connect function, this will be of the type of all your reducers. MiddlewareAPI have two members which one is a function getState() that return an object of type “S” and dispatch field of type Dispatch S.

It’s still not straightforward since the translated TypeScript also uses the three fat arrows. If we come back to the first line, the first confusion may be that it starts with “S”. The syntax is borrowed from a generic method which “loggerMiddleware” use as an anonymous function. You can see this line as:

function loggerMiddleware<S>(api: MiddlewareAPI<S>) ...

It would be better to have a stronger definition than relying on the generic type when accessing the state with api.getSTate(), however, the contract is defined to receive the generic in Redux.

export interface Middleware {
  <S>(api: MiddlewareAPI<S>): (next: Dispatch<S>) => Dispatch<S>;
}

export function applyMiddleware(...middlewares: Middleware[]): GenericStoreEnhancer;

As you see, the Middleware function is used by applyMiddleware to hold a collection of this one. This is why your middleware must conform to the same signature.

One last detail is that even with the type <S> at the MiddlewareAPI<S> parameter level, this one won’t give you a great experience when using app.getState() because it won’t be from your Redux State strongly type. To have MiddlewareAPI to still be generic but specific to your Redux state, you just need to extend this one to your type. Here is an example that also bring the ExtendedMiddleware interface to have a strong middleware type but this is not required.

import { Middleware, MiddlewareAPI, Dispatch, Action } from "redux";
export interface ExtendedMiddleware<StateType> extends Middleware {
    <S extends StateType>(api: MiddlewareAPI<S>): (next: Dispatch<S>) => Dispatch<S>;
}

export const loggerMiddleware: ExtendedMiddleware<YourApplicationReduxStateTypeHere> = <S extends YourApplicationReduxStateTypeHere>(api: MiddlewareAPI<S>) =>
    (next: Dispatch<S>) =>
        <A extends Action>(action: A): A => {
            console.log("Before");
            const result = next(action);
            console.log("After"); // Can use: api.getState()
            return result;
        };

So, this post probably didn’t demystify totally what is going on with Redux middleware but increased the awareness of each of these variables. Hopefully, if you are using TypeScript you will type your middleware to remove some confusions about what is the role of each of the variable passed down.

TypeScript and Restricting String to Interface Members

Imagine the scenario where you have an interface with many members. Each of them is a boolean and your React component allows you to toggle with a checkbox the value of them. You have a single method that will dispatch the action to your Redux/Flux cycle. How can you make your code strong enough and still be flexible to not having 1 function per member?

The solution resides that we do not one to allow every string but just a finite set of string which is the members’ name of a specific interface.

public render(): JSX.Element {
// ...
<input
            type="checkbox"
            checked={this.props.myModel.member1}
            onClick={(e) => { this.onToggle("member1"); }} />
// ...
}

The click method won’t ask for a string, but for a key of the model.

private onToggle(filterName: keyof MyModel) {
        this.props.onToggle(filterName);
}

This little difference makes the whole system being flexible since it allows to type string, but strict in a way that we have a defined set of potential value. The set is also dynamic. If you rename a member, add or remove a member from the interface, TypeScript will come in play and warn if something is invalid.

In this article, we saw a way to use string to indicate which value to change. Since interfaces are stripped out at transpilation time, there is some case like the one presented that providing a string is the only solution. TypeScript allows the use of keyof to extract a set of string from an interface which allows having a finite set of accepted results and hence reinforce your code by eliminate wrong inputs.

TypeScript, React and Redux Part 5 : Reducer with Different Actions

TypeScript’s type can be highlighting to what is going on if you have been doing Javascript for a while. This is shockingly true if you look at Redux’s reducers. Usually, a reducer takes two parameter which is the state and the action. The state passed is the same type that the reducer’s return type. It contains the actual data before the reducer come in play. The parameter named “action” is an object with at least a string that defines what type of action is being invoked as well as the information that needs to be saved in the state. The reducer’s role is to take the payload (information) and set this one at the right position in the state before returning it.

In JavaScript, the second parameter, the action, can change shape. For example, if your reducer is for your users (let’s call it “usersReducer”), this one can let you update users information, as well as their relationship. You won’t send back the whole user’s state every time. You may just send a list of ids for the relation. Hence, in JavaScript, you could pass in the payload one that is the whole user object when the user gets created or updated, but only a list of integers when the relationship list is changed to one of these users. In JavaScript, it won’t matter because depending on the string you pass to determine the type of action, you go to a different branch of code which you will access and work with the expected format of data you know you are passing. Here is a quick example with two actions. One to create, one to update a user’s relationship.

function myReducer(
    state
    action) {
        
    if (action.type === ACTION_CREATE) {
        const immutableData = {...state};
        immutableData[action.payload.userId] = action.payload.newUser;
        return immutableData;
    } else if (action.type === ACTION_UPDATE_LIST_RELATIONSHIPS) {
        const immutableData = {...state};
        immutableData[action.payload.userId].relationShipIds = action.payload.ids;
        return immutableData;
    } 
    return state;
}

We can see that the action argument shape change depending on the type. This is totally valid in JavaScript, but require more work in TypeScript.

In TypeScript, types must be defined. That means that we need to pass a known type for the second argument. This is where it’s convenient to have a generic action object that allows you to reuse some part like the one specify the type as well as the payload. Since the payload varies, the use of generic makes sense.

export interface Actions<T> {
    readonly type: string;
    payload: T;
}

You can extend this interface with other members if desired or simply enhance this one directly. From there, you can have your reducer to use a union of potential action:

function myReducer(
    state: UsersState,
    action: Actions<UsersState> | Actions<User> | Actions<{userId:number, ids:number[]}>): UsersState {
    if (action.type === ACTION_CREATE) {
        const immutableData = {...state};
        immutableData[action.payload.userId] = action.payload.;
        return immutableData;
    } else if (action.type === ACTION_UPDATE_LIST_RELATIONSHIPS) {
        const immutableData = {...state};
        immutableData[action.payload.userId].relationShipIds = action.payload.ids;
        return immutableData;
    } 
    return state;
}

The problem with the code above is that it doesn’t transpile. TypeScript will not know which type is the action and won’t let you use the object. You need to user defined typed guard which will tell TypeScript which type is actually the argument. With the generic action, we can use also a generic typed guard.

export function isGenericAction<T>(obj: any): obj is Actions<T> {
    const castedObject = (obj as Actions<T>);
    return castedObject.payload !== undefined && castedObject.type !== undefined;
}

The next step is to use the check with the type in conditions.

function myReducer(
    state: UsersState,
    action: Actions<UsersState> | Actions<User> | Actions<UserRelationships>): UsersState {
    if (action.type === ACTION_CREATE && GenericAction<User>(action)) {
        const immutableData = {...state};
        immutableData[action.payload.userId] = action.payload.;
        return immutableData;
    } else if (action.type === ACTION_UPDATE_LIST_RELATIONSHIPS && GenericAction<UserRelationships>(action)) {
        const immutableData = {...state};
        immutableData[action.payload.userId].relationShipIds = action.payload.ids;
        return immutableData;
    } 
    return state;
}

The code above compiles and it allows you to use a single reducer with many different actions’ payload. An alternative idea could be to have a single reducer per payload type, but this gets fast cumbersome the more your domain grows and require more consolidation once you get back to your React component. Your reducers should be designed to be flat, but also to support the idea of a specific domain. In the example above, a single reducer for user management makes sense.

In this article, we saw that JavaScript allows us to have mixed kind of data in a single argument which we would act differently depending on the type (specified in a string). Then, we realized that when it’s time to type, that it can be problematic since TypeSCript expects to have a clear idea of what type is needed before proceeding with the information. Finally, a solution that embraces strong type, union and type guard was proposed to accommodate Redux and being strongly typed.

Articles of the series:

  1. TypeScript, React and Redux
  2. TypeScript and Redux Store
  3. TypeScript Redux Store Binding
  4. TypeScript Redux Action Creators
  5. TypeScript, React and Redux Part 5 : Reducer with Different Actions

How I Migrated an Existing AngularJs Project from JavaScript to TypeScript (Part 2 of 2)

In part 1 of how to migrate an existing JavaScript project to TypeScript, we saw that we can have only JavaScript files and use TypeScript as transpiler with almost no effort. This gave us the capability to transpile into a different version of EcmaScript, but also open the door to bringing typed object and primitives in an existing project. In this phase 2, we will change TypeScript to allows .ts file and benefit of strongly typed parameters and objects.

As a reminder, the project that I was migrating to TypeScript was an AngularJS 1.5, with RequireJs as AMD loader that was using Grunt to workout the files. In part 1, we configured TypeScript to read only .js file. Now, we need to read both, but also to use AMD module. This wasn’t required in the first place and still isn’t because of the way the actual project was built — it was explicitly using the requireJs library in all files. The tsconfig.json also specify what we want to include: .ts file. I added the “checkjs” to report errors in JavaScript file. This is not required, but since it’s a phase 2, I desired to kick the notch up more in term of validation. However, the checkjs is limited since it relies on inference or JsDoc comment style which wasn’t used in the project that I was converting.

Few changes are required in term of libraries. We need to bring some definition files for AngularJS, RequireJs, JQuery and Angular-ui-router and also the Angular library. This can be done easily with NPM, here is the JSON output.

"angular": "^1.5.11",
"@types/angular": "^1.5.23",
"@types/angular-ui-router": "^1.1.37",
"@types/jquery": "^3.2.10",

Minor changes was required in the Gruntfile.js because if we recall, we were using the tsconfig.json file to do the heavy lifting. The main change was to bring .ts file into the final distribution folder since we want to debug the .ts with the map file.

From there, I chose some JavaScript files, and changed the extension of the file to .ts. I started with the entry JavaScript file and went deeper and deeper. Without modifying anything, it was working. But, it wasn’t leveraging the typed aspect of TypeScript. That is the reason, I started to change all requirejs type. When “angular” was injected, I added to the parameter the type. Almost every file needed to have ng.IAngularStatic

angular: ng.IAngularStatic

The definition file are well exhaustive and provides everything from compileProvider, to scsDelegateProvider, to httpProvider and so on. With the power of TypeScript, it’s a matter of typing “ng.” and wait for Intellisense to come up suggesting type from AngularJS’ definition file.

Finally, I went into a situation where this project was using another of our project that was written in JavaScript. No definition file was available. However, I wanted to have the return object to be typed. I ended up creating a folder, in the project I am converting, that I called “CustomDefinitionFiles” and I added the missing type and used it. Be sure to have the extension “.d.ts” and you will be able to use it in your project. While it’s better to have the definition files provided by the library, this give us a quick way to have typed content without forcing anything.

At the end of these two phases, I was able to show that an existing JavaScript project can be converted to use TypeScript without any impact on the actual code. I demonstrate that it’s possible to live in a hybrid mode where JavaScript and TypeScript co-exist. Finally, I demonstrated the power of type by not having a system that is getting type progressively without creating any burden for developers. No one in the team was affected by this transformation and in long term, the code base will get in better quality, easier to read and maintain.

First part of AngularJs to React

How I Migrated an Existing AngularJs Project from JavaScript to TypeScript (Part 1 of 2)

A few weeks ago, I had to present the benefits of TypeScript to a group of people. One argument was that many projects were built in JavaScript, so bringing a new tool to the mix would create a disparity amongst the fleet of repositories we need to maintain. This is a valid argument when we have many different languages like Java, C#, C++, Python, but is it when TypeScript is a superset of JavaScript? No that much since going with TypeScript allows you to still work in JavaScript if desired. Coming back to JavaScript from TypeScript is allow smooth since you could always transpile into EcmaScript 6 and work from the output. Nevertheless, it’s an interesting exercise to demonstrate how to migrate an existing AngularJs project from JavaScript into TypeScript. This also may be a good argument to switch to TypeScript since it’s easy and bring all the power of strongly typed language and still be very close of JavaScript.

Before going any further, let’s see what kind of project we will migrate. First, it’s using AngularJS 1.5. Any version before 2 was built in JavaScript. There is an official definition file available which will be required to fetch during our conversion. Second, the project is using RequireJs as the module loader. Again, this is not an issue since RequireJs has also official definition file. Third and last, this project is using Grunt as tasks manager. This is pretty old since the community drifted to Gulp and now Webpack. However, this won’t be a problem since TypeScript has a Grunt library.

The first step is to bring TypeScript into the project and this can be done easily by using NPM. This project was using mostly Bower, but also NPM. Since I am more familiar with NPM, I decided to use NPM to fetch TypeScript.

npm install typescript --save-dev

We also need to get the Grunt library that will bridge Grunt and Typescript.

npm install grunt-ts --save-dev

Now that we have the tool to transpile, let’s do the migration in two phases. The first phase will be to keep every JavaScript in .js file and only use it as a transpiler. We will change some JavaScript file to use the latest EcmaScript and transpile using TypeScript to EcmaScript 3. The second phase will be to migrate files to be TypeScript (.ts) file. To have TypeScript transpiler configured for the need of reading JavaScript, we must specify that TypeScript is allowed to get into JavaScript file. The actual project is having its source code in a folder named public and was using Grunt’s task to move the code to distribute in a folder named dist. Since the goal is to migrate without modifying too much, we will introduce a dist_tsfolder that will be then moved to the dist folder. At the end, the dist folder remains the folder to use to deploy and the public folder the source folder to modify. We just created an intermediary folder to output our TypeScript file and do some modifications. In the following configuration, you will see all what we just discussed.

{
     "compilerOptions": 
      {         
         "outDir": "./dist_ts",         
         "allowJs": true,         
         "target": "es3",         
         "rootDir": "./"     
        },     
"include": [         
       "./public/**/*.js"     
         ],     
        "exclude": [       
            "./public/assets/"     
   ] 
} 

For phase 2, we will have to change the include and bring few other configurations, but so far, it does what we want. We just need to put the configuration in tsconfig.json and we are all set to go in the Gruntfile.js to create a task to build TypeScript.

ts: {           
   default: {                
      tsconfig: true           
   }      
}

This step as you can see was pretty straightforward. The only thing it says is to read the configuration file. However, a little more work was required to have TypeScript to work properly. The first thing is that this project has a requirejs Grunt task that was using the public folder to bring the whole code into a single JavaScript file. This couldn’t point to the public folder since we output the JavaScript in dist_ts. It’s not a big deal. We need to change the mainConfigFile path of requirejs to point to the intermediary folder. However, the requirejs task needed to have access to some assets and third library that was under the public folder. So, a pre-build task was required before calling the Gulp’s TypeScript task to move some files in dist_ts. And finally, a post-build task to move all the generated JavaScript file and JavaScript’s map file in the final destination folder.

From here, any actual JavaScript file could be changed to use “const” or the fat arrow way to work with function and this one will be with “var” and conventional function at the end.

Migrating from JavaScript with a big framework like Angular can be done in steps. So far in this phase 1, we were able to bring TypeScript very smoothly without disrupting any actual JavaScript code. In a next article, we will see phase two which is to bring TypeScript file parallel to JavaScript file to run in a hybrid mode where both can cohabit.

Migrating from AngularJS to React Part 2