How to properly import and use the MSAL (Microsoft Authentication Library for js) into a typescript react single page application?

28,481

Solution 1

As you have correctly mentioned - in the msal.d.ts there are no exports - its not a module, and therefore you should not try importing.

Instead you can use it like this:

/// <reference path="./node_modules/msal/out/msal.d.ts" />

const userAgentApplication = new Msal.UserAgentApplication("your_client_id", null, (errorDes, token, error, tokenType) =>
    {

    });

Note that even in readme they specify only one way of using their library - by including script tag, not by importing module. And further looking into their source code shows they are not using modules as well.

Solution 2

It looks like the latest version of MSAL.js does have a CommonJS export. You can now just do the following in TypeScript (tested with version 2.3.3 of TypeScript and 0.1.3 of MSAL.js):

import * as Msal from 'msal';

Now in your .ts (or in my case .tsx file) you can, for instance, setup a click event handler and create a UserAgentApplication object:

// In you class somewhere
private userAgentApplication: any = undefined;

// The login button click handler
handleLoginClick = (event: any): void => {
    if (!this.userAgentApplication) {
        this.userAgentApplication = new Msal.UserAgentApplication(
            'clientID string', 'authority string or empty', this.authCallback, { cacheLocation: 'localStorage'});
    }
    // Other login stuff...
}

// In React render()
public render() {
    return (
        <Button
            bsStyle="warning"
            type="button"
            onClick={(e) => this.handleLoginClick(e)}
        >
        Log in
        </Button>
    );
}

Solution 3

I had the same issue and couldn't wait for the author to fix it, so forked and modified the original code. Just as a temporary fix you can use my version msalx instead of msal.

npm install msalx

You can find the source code and an example usage in react at: https://github.com/malekpour/microsoft-authentication-library-for-js#example

Solution 4

If you install the exports-loader (npm install exports-loader --save-dev) you can avoid the script tag and add the following to your directives:

var Msal = require("exports-loader?Msal!../../../node_modules/msal/out/msal.js"); 
Share:
28,481

Related videos on Youtube

nbrowne
Author by

nbrowne

I'm a software professional and software development manager who's passionate about technology, creating great solutions, building teams, and remote work. I have a B.Sc. and M.Sc. in Computer Science, and my M.Sc. specialized in artificial intelligence. I've worked in Canada, Mexico and the United States building software systems and currently lead a small development team. For more information or to chat, you can find me on LinkedIn at https://www.linkedin.com/in/nigelbrowne/ and https://nigelbrowne.com.

Updated on July 09, 2022

Comments

  • nbrowne
    nbrowne almost 2 years

    Problem

    I can't seem to get the MSAL library to import properly into my typescript code. I'm using the MSAL for JS library (which is supposed to have typings) in a simple typescript/react project scaffolded using the create-react-app with react-typescript scripts. I'm new to typescript and not sure if I'm missing something obvious or if there is a problem with the MSAL package when using it with typescript projects.

    Details:

    1. I added the MSAL package from NPM using npm install --save msal.
    2. I attempted to import the MSAL into my .ts using different forms of import {Msal} from 'msal';
    3. This results in a typescript error Could not find a declaration file for module 'msal'. '<path>/node_modules/msal/out/msal.js' implicitly has an 'any' type.
    4. Thinking that was odd, I looked at the the node_module/msal/out folder and saw a 'msal.d.ts' file, which is what I would expect.
    5. When I look at the contents of the msal.d.ts file, I don't see any exports, which I would normally expect to see.
    6. I tried install the declaration from @types using npm install --save-dev @types/msal, but it doesn't exist.
    7. I also tried importing it into my file using let Msal = require('Msal');, but get an error that the Msal.UserAgentApplication isn't a constructor.
    8. I didn't have much luck trying to use the /// reference directive and adding a script tag to the main index.html. This also doesn't feel like the right way to solve the problem.

    ExampleMsal.ts

    import { observable, action, computed } from 'mobx';
    import * as Msal from 'msal'; // <-- This line gives the error
    
    class ExampleMsal{
        @observable 
        private _isLoggedIn: boolean;
    
        constructor() {
            this._isLoggedIn = false;
        }
    
        @computed 
        get isLoggedIn(): boolean {
            return this._isLoggedIn;
        }
    
        @action 
        signIn() {
    
            let userAgentApplication = new Msal.UserAgentApplication('<client-id>', null, 
            function (errorDes: string, token: string, error: string, tokenType: string) {
                // this callback is called after loginRedirect OR acquireTokenRedirect 
                // (not used for loginPopup/aquireTokenPopup)
            }
            );
    
            userAgentApplication.loginPopup(['user.read']).then(function(token: string) {
                let user = userAgentApplication.getUser();
                if (user) {
                    // signin successful
                    alert('success');
                } else {
                    // signin failure
                    alert('fail');
                }
            }, function (error: string) {
                // handle error
                alert('Error' + error);
            });        
            this._isLoggedIn = true;
        }
    
        @action 
        signOut() {
            this._isLoggedIn = false;
        }
    }
    
    export default ExampleMsal;
    

    tsconfig.json

    {
      "compilerOptions": {
        "outDir": "build/dist",
        "module": "commonjs",
        "target": "es5",
        "lib": ["es6", "dom"],
        "sourceMap": true,
        "allowJs": true,
        "jsx": "react",
        "moduleResolution": "node",
        "rootDir": "src",
        "forceConsistentCasingInFileNames": true,
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "noImplicitAny": true,
        "strictNullChecks": true,
        "suppressImplicitAnyIndexErrors": true,
        "noUnusedLocals": true,
        "experimentalDecorators": true
      },
      "exclude": [
        "node_modules",
        "build",
        "scripts",
        "acceptance-tests",
        "webpack",
        "jest",
        "src/setupTests.ts"
      ],
      "types": [
        "typePatches"
      ]
    }
    
  • nbrowne
    nbrowne almost 7 years
    The reference path definition combined with including the js file from the CDN in my index.html got it working for me. I'll update back if I figure out a cleaner way to do it.
  • Thiago Custodio
    Thiago Custodio almost 7 years
    Hi Nigel, can you upload your project to your Github? I am trying to find samples with React and MSAL. Thanks in advance
  • Paweł Skorupiński
    Paweł Skorupiński over 6 years
    I am getting exception: Unexpected '!' in 'exports-loader?Msal!./node_modules/msal/out/msal.js'. Do not use import syntax to configure webpack loaders import/no-webpack-loader-syntax
  • Dibran
    Dibran over 6 years
    You sir are a hero
  • Jed
    Jed over 6 years
    I was able to import using this but I am getting the following error: Msal.UserAgentApplication is not a constructor
  • RHarris
    RHarris over 6 years
    I've been able to do what you suggested to new up a UserAgentAppliation, however, in previous code (where I loaded Msal from CDN), I did the following Msal.Storage("localStorage").getItem(...). This now gives an error when I use import * as Msal from 'msal'. Is there a way to make that work?
  • StephenD
    StephenD over 6 years
    Later versions of MSAL seem to work well now, I'm using version 0.1.3, and it a simple: import * as Msal from 'msal'; works well.