Quickstart: Acquire an access token and call the Microsoft Graph API from an Electron desktop app

In this quickstart, you download and run a code sample that demonstrates how an Electron desktop application can sign in users and acquire access tokens to call the Microsoft Graph API.

This quickstart uses the Microsoft Authentication Library for Node.js (MSAL Node) with the authorization code flow with PKCE.

Prerequisites

Register and download the sample application

Follow the steps below to get started.

Step 1: Register the application

To register your application and add the app's registration information to your solution manually, follow these steps:

  1. Sign in to the Azure portal.
  2. If you have access to multiple tenants, use the Directory + subscription filter in the top menu to select the tenant in which you want to register an application.
  3. Search for and select Azure Active Directory.
  4. Under Manage, select App registrations > New registration.
  5. Enter a Name for your application, for example msal-node-desktop. Users of your app might see this name, and you can change it later.
  6. Select Register to create the application.
  7. Under Manage, select Authentication.
  8. Select Add a platform > Mobile and desktop applications.
  9. In the Redirect URIs section, enter msal://redirect.
  10. Select Configure.

Step 1: Configure the application in Azure portal

For the code sample for this quickstart to work, you need to add a reply URL as msal://redirect.

Already configured Your application is configured with these attributes.

Step 2: Download the Electron sample project

Note

Enter_the_Supported_Account_Info_Here

Step 3: Configure the Electron sample project

  1. Extract the zip file to a local folder close to the root of the disk, for example, C:/Azure-Samples.

  2. Edit .env and replace the values of the fields TENANT_ID and CLIENT_ID with the following snippet:

    "TENANT_ID": "Enter_the_Tenant_Id_Here",
    "CLIENT_ID": "Enter_the_Application_Id_Here"
    

    Where:

    • Enter_the_Application_Id_Here - is the Application (client) ID for the application you registered.
    • Enter_the_Tenant_Id_Here - replace this value with the Tenant Id or Tenant name (for example, contoso.microsoft.com)

Tip

To find the values of Application (client) ID, Directory (tenant) ID, go to the app's Overview page in the Azure portal.

Step 4: Run the application

Step 4: Run the application

You'll need to install the dependencies of this sample once:

npm install

Then, run the application via command prompt or console:

npm start

You should see application's UI with a Sign in button.

About the code

Below, some of the important aspects of the sample application are discussed.

MSAL Node

MSAL Node is the library used to sign in users and request tokens used to access an API protected by Microsoft identity platform. For more information on how to use MSAL Node with desktop apps, see this article.

You can install MSAL Node by running the following npm command.

npm install @azure/msal-node --save

MSAL initialization

You can add the reference for MSAL Node by adding the following code:

const { PublicClientApplication } = require('@azure/msal-node');

Then, initialize MSAL using the following code:

const MSAL_CONFIG = {
    auth: {
        clientId: "Enter_the_Application_Id_Here",
        authority: "https://login.microsoftonline.com/Enter_the_Tenant_Id_Here",
    },
};

const pca = new PublicClientApplication(MSAL_CONFIG);
Where: Description
clientId Is the Application (client) ID for the application registered in the Azure portal. You can find this value in the app's Overview page in the Azure portal.
authority The STS endpoint for user to authenticate. Usually https://login.microsoftonline.com/{tenant} for public cloud, where {tenant} is the name of your tenant or your tenant Id.

Requesting tokens

In the first leg of authorization code flow with PKCE, prepare and send an authorization code request with the appropriate parameters. Then, in the second leg of the flow, listen for the authorization code response. Once the code is obtained, exchange it to obtain a token.

// The redirect URI you setup during app registration with a custom file protocol "msal"
const redirectUri = "msal://redirect";

const cryptoProvider = new CryptoProvider();

const pkceCodes = {
    challengeMethod: "S256", // Use SHA256 Algorithm
    verifier: "", // Generate a code verifier for the Auth Code Request first
    challenge: "" // Generate a code challenge from the previously generated code verifier
};

/**
 * Starts an interactive token request
 * @param {object} authWindow: Electron window object
 * @param {object} tokenRequest: token request object with scopes
 */
async function getTokenInteractive(authWindow, tokenRequest) {

    /**
     * Proof Key for Code Exchange (PKCE) Setup
     *
     * MSAL enables PKCE in the Authorization Code Grant Flow by including the codeChallenge and codeChallengeMethod
     * parameters in the request passed into getAuthCodeUrl() API, as well as the codeVerifier parameter in the
     * second leg (acquireTokenByCode() API).
     */

    const {verifier, challenge} = await cryptoProvider.generatePkceCodes();

    pkceCodes.verifier = verifier;
    pkceCodes.challenge = challenge;

    const authCodeUrlParams = {
        redirectUri: redirectUri
        scopes: tokenRequest.scopes,
        codeChallenge: pkceCodes.challenge, // PKCE Code Challenge
        codeChallengeMethod: pkceCodes.challengeMethod // PKCE Code Challenge Method
    };

    const authCodeUrl = await pca.getAuthCodeUrl(authCodeUrlParams);

    // register the custom file protocol in redirect URI
    protocol.registerFileProtocol(redirectUri.split(":")[0], (req, callback) => {
        const requestUrl = url.parse(req.url, true);
        callback(path.normalize(`${__dirname}/${requestUrl.path}`));
    });

    const authCode = await listenForAuthCode(authCodeUrl, authWindow); // see below

    const authResponse = await pca.acquireTokenByCode({
        redirectUri: redirectUri,
        scopes: tokenRequest.scopes,
        code: authCode,
        codeVerifier: pkceCodes.verifier // PKCE Code Verifier
    });

    return authResponse;
}

/**
 * Listens for auth code response from Azure AD
 * @param {string} navigateUrl: URL where auth code response is parsed
 * @param {object} authWindow: Electron window object
 */
async function listenForAuthCode(navigateUrl, authWindow) {

    authWindow.loadURL(navigateUrl);

    return new Promise((resolve, reject) => {
        authWindow.webContents.on('will-redirect', (event, responseUrl) => {
            try {
                const parsedUrl = new URL(responseUrl);
                const authCode = parsedUrl.searchParams.get('code');
                resolve(authCode);
            } catch (err) {
                reject(err);
            }
        });
    });
}
Where: Description
authWindow Current Electron window in process.
tokenRequest Contains the scopes being requested, such as "User.Read" for Microsoft Graph or "api://<Application ID>/access_as_user" for custom web APIs.

Next steps

To learn more about Electron desktop app development with MSAL Node, see the tutorial: