skip to Main Content

I have implemented Azure authentiation in web API created in angular 10 application. While authenticating using URL "https://login.microsoftonline.com/" I am getting Request failed with status 400 inside MSAL-NODE while calling networkClient.sendPostRequestAsync(tokenEndpoint, options). Here is detailed error I am getting and code snippet. I am using @azure/[email protected]

Code:

async callMSClient(): Promise<any> {
    const msalConfig = {
      auth: {
        clientId: config.get("msConfig.clientId"),
        authority: config.get("msConfig.aadEndPoint") + config.get("msConfig.tenantId"),
        clientSecret: config.get("msConfig.clientSecret"),
        redirectUri: config.get("msConfig.redirectUri"),
        knownAuthorities: ["login.microsoftonline.com"]
      }
    };
    const tokenRequest = {
      scopes: [config.get("msConfig.graphEndPoint") + '.default'],
    };
    const cca = new msal.ConfidentialClientApplication(msalConfig);
    return cca.acquireTokenByClientCredential(tokenRequest).then(data => {
      return data;
    }).catch(e=>{
      console.log(e);
    });
    
  }

Error:

ClientAuthError: network_error: Network request failed
at createClientAuthError (C:ProjectAngTestnode_modules@azuremsal-commondisterrorClientAuthError.mjs:255:12)
at NetworkManager.sendPostRequest (C:ProjectAngTestnode_modules@azuremsal-commondistnetworkNetworkManager.mjs:35:23)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at ClientCredentialClient.executePostToTokenEndpoint (C:ProjectAngTestnode_modules@azuremsal-commondistclientBaseClient.mjs:79:26)     
at ClientCredentialClient.executeTokenRequest (C:ProjectAngTestnode_modules@azuresrcclientClientCredentialClient.ts:295:30)
at ConfidentialClientApplication.acquireTokenByClientCredential (C:ProjectAngTestnode_modules@azuresrcclientConfidentialClientApplication.ts:166:20) {

errorCode: ‘network_error’,
errorMessage: ‘Network request failed’,
subError: ”,
correlationId: ‘ef035f69-5522-4224g-633s-ccddd950b2hg’

When I deep dive into error list, while debugging I found two error infact, one is error 400 stating bad request and another is "Self Singed In Certificate Chain" error which seems I have to install a certificate in my local machine for localhost.

2

Answers


  1. Chosen as BEST ANSWER

    Here is the alternate for the problem I applied to solution.I acknowldge that @sridevi solution should work mostly but I had another problem also which I found only after deep dive. Posting if someone else is facing similar problem.

    1. Stringify the body before sending to API call.
    2. You can directly call Microsoft Oauth token url using axios.
    3. If you are getting Self Signed in certificate chain error, you can temporarily disable the check using https agent.

    Below code worked for me.

    I used grant_type:"client_credentials" and added custom agent const agent=new https.Agent({rejectUnauthorized:false}) to disable Self Signed in Certificate chain error. This is not recommended but for testing on localhost it worked for me. In higher environment you should add verified certificate from CA.

    async callApi(accessToken) {
        const agent=new https.Agent({rejectUnauthorized:false});
        const url= "https://login.microsoftonline.com/{{id}}/oauth2/v2.0/token";
            const body = new URLSearchParams({
              client_id: config.get("msConfig.clientId"),
              grant_type:"client_credentials",
              client_secret: config.get("msConfig.clientSecret"),
              scope:"https://graph.microsoft.com/.default"  
            })
       
        try {
            const response = await axios.post (url, body, { 
                responseType:"json",
                headers:{
                    'Content-Type': 'application/x-www-form-urlencoded'
                },httpsAgent: agent});
            
            return {accessToken: response.data.access_token,
                status: response.status
            };
        } catch (error) {
            console.log(error)
            return error;
        }
    }


  2. Initially, I registered one application and granted API permission of Application type as token generation uses client credentials flow:

    enter image description here

    Now, I ran below commands to create a project and installed dependencies in it:

    mkdir azure-auth-node
    cd azure-auth-node
    npm init -y
    
    npm install @azure/msal-node express dotenv
    

    In my case, I created following code files to generate the token with client credentials flow:

    .env:

    TENANT_ID=tenantId
    CLIENT_ID=appId
    CLIENT_SECRET=secret
    AUTHORITY=https://login.microsoftonline.com/tenantId
    GRAPH_SCOPE=https://graph.microsoft.com/.default
    

    auth.js:

    const { ConfidentialClientApplication } = require("@azure/msal-node");
    require("dotenv").config();
    
    const msalConfig = {
      auth: {
        clientId: process.env.CLIENT_ID,
        authority: process.env.AUTHORITY,
        clientSecret: process.env.CLIENT_SECRET,
      },
    };
    
    const tokenRequest = {
      scopes: [process.env.GRAPH_SCOPE], // e.g., https://graph.microsoft.com/.default
    };
    
    const cca = new ConfidentialClientApplication(msalConfig);
    
    async function getAccessToken() {
      try {
        const response = await cca.acquireTokenByClientCredential(tokenRequest);
        return response.accessToken;
      } catch (error) {
        console.error("Error acquiring token:", error);
        throw error;
      }
    }
    
    module.exports = { getAccessToken };
    

    index.js:

    const express = require("express");
    const { getAccessToken } = require("./auth");
    
    const app = express();
    const PORT = 3000;
    
    app.get("/api/token", async (req, res) => {
      try {
        const token = await getAccessToken();
        res.json({ token });
      } catch (error) {
        res.status(500).json({ error: "Failed to fetch token" });
      }
    });
    
    app.listen(PORT, () => {
      console.log(`Server running on http://localhost:${PORT}`);
    });
    

    When I started the server with node index.js command and ran below URL in browser, I got the token successfully as below:

    http://localhost:3000/api/token
    

    enter image description here

    You can use this token to list users by calling below Microsoft Graph API call:

    GET https://graph.microsoft.com/v1.0/users
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search