Cannot access Microsoft Graph without user - the 'grant_type' is not present in the body

I am eager to dive into Microsoft Azure and Graph by creating a simple application that will utilize the Graph API as a background worker. Although I currently only have a demo account, I believe this should not pose a problem.

I am following along with this tutorial:

https://learn.microsoft.com/en-us/graph/auth-v2-service#4-get-an-access-token

since I do not require a user account for this process. My initial goal is to obtain an access token using Axios. Given that I use NestJs, Axios is encapsulated within an HTTP module.

So far, I have set up the request as follows:

async getToken(): Promise<any> {
    const requestURL: string = 'https://login.microsoftonline.com/2c1714e1-1030-4da9-af5e-59630d7fe05f/oauth2/v2.0/token';

    const requestBody: object = {
        tenant: '2c1714e1-1030-4da9-af5e-59630d7fe05f',
        client_id: 'bec52b71-dc94-4577-9f8d-b8536ed0e73d',
        scope: 'https://graph.microsoft.com/.default',
        client_secret: 'OV/NkBIWH7d3G/BGyJQN3vxQA]fT6qK@',
        grant_type: 'client_credentials',
    };

    const requestConfiguration: object = {
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
    };

    const observableResult: Observable<AxiosResponse<any>> = this.httpService.post(requestURL, requestBody, requestConfiguration);
    return observableResult.toPromise();
}

Upon execution, I encounter a 400 HTTP error along with the message:

"AADSTS900144: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID: 038a3bf5-9396-4a4c-9dd6-b4608f265800\r\nCorrelation ID: a1871bfc-af0d-470e-b604-f94ea4f10325\r\nTimestamp: 2019-12-21 23:10:11Z"

Have I misinterpreted the documentation? What might be missing or incorrect in my setup? Thank you for any guidance in advance.

Answer №1

Your information is accurate (postman receives token with your data). However, it appears that there was a mistake made when submitting the POST request.

According to the documentation you provided, the correct Content-Type should be set to

application/x-www-form-urlencoded
. Therefore, you must first convert the requestBody into URL encoded form (key=value&key2=value2) and include it in the body of the request instead of appending it to the URL. This can be a less obvious step...

const requestURL: string = 'https://login.microsoftonline.com/2c1714e1-1030-4da9-af5e-59630d7fe05f/oauth2/v2.0/token';

const requestBody: object = {
    tenant: '2c1714e1-1030-4da9-af5e-59630d7fe05f',
    client_id: 'bec52b71-dc94-4577-9f8d-b8536ed0e73d',
    scope: 'https://graph.microsoft.com/.default',
    client_secret: 'OV/NkBIWH7d3G/BGyJQN3vxQA]fT6qK@',
    grant_type: 'client_credentials',
};

let request = Object.keys(requestBody).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(requestBody[k])}`).join('&')
this.httpService.post(requestURL, request, { headers: { 'content-type': 'application/x-www-form-urlencoded' } })

Answer №2

Retrieve access token:

'use strict';

const axios = require('axios');
const qs = require('qs');

const generateAccessToken = (tenantId, clientId, clientSecret, resource) => {
    const data = {
        resource: resource,
        grant_type: 'client_credentials',
    };
    
    return axios({
        url: `https://login.windows.net/${tenantId}/oauth2/token`,
        method: "post",
        headers: { 'content-type': 'application/x-www-form-urlencoded' },
        auth: {
            username: clientId,
            password: clientSecret,
        },
        data:  qs.stringify(data)
    }).catch(error => {
        throw error;
    })
};

Usage example:

generateAccessToken(<tenantId>, <clientId>, <clientSecret>, 'https://graph.microsoft.com').then(response => {
    console.log(`Access token retrieved successfully`);
    const token = JSON.stringify(response.data.access_token);

    // Perform necessary actions with the access token

}).catch(err => {
     console.log("Error occurred: " + err);
     throw err;
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

An Uncaught Error has occurred: The module titled "functions" has not been loaded within the current context _. To resolve this issue, please make sure to use

I've been grappling with setting up TypeScript in my ASP.NET Core project without much success. Initially, I managed to implement a basic functionality where an alert pops up when the page loads successfully. My next challenge was to manually conver ...

Circular dependency issue in NestJS

Within my NestJS module, I encountered a situation where I needed services to reference each other, resulting in a circular dependency. Following the guidance from the NestJS documentation, I utilized @ForwardRef: https://i.sstatic.net/V0bqvjrt.png Despi ...

Exploring the elements within the ContentChildren directive in Angular

Presenting my component: import { Component, OnInit, ContentChildren, QueryList } from '@angular/core'; import { IconBoxComponent } from '../icon-box/icon-box.component'; @Component({ selector: 'app-three-icon-box', temp ...

Guide on enabling external API login with Next Auth v5 in Next.js 14 using the application router

While trying to navigate the documentation for Next Auth, I found myself struggling with outdated examples and an overall lack of clarity. It appears that the documentation is still a work in progress, making it challenging to find reliable information on ...

Wrapper functions that are nested are returning a Promise that resolves to another Promise of type T

I have a function called doesPromiseyThings that wraps a thunk and returns its value inside a Promise. I want to create another wrapper that not only handles the creation of thunks, but also ensures the returned type is a Promise-wrapped version of the ori ...

Build a unique array of identifiers extracted from an object

https://i.sstatic.net/PaFXj.png I am seeking advice on how to extract an array of IDs values by iterating through an object in React JS. https://i.sstatic.net/GV6ga.png const initialState = useMemo(()=> { return dataTable.filter(result => f ...

``There seems to be an issue with the Deno logger FileHandler as it

I am currently in the process of setting up loggers for an application. I have a handler named console which logs every event to the console. Additionally, there is a handler called app that is supposed to log all events to a file. While the logs are succ ...

Updating the background color using typescript

Before transitioning to angular development, I had experience working with vanilla Javascript. I encountered a challenge when trying to modify the css properties of specific elements using Typescript. Unfortunately, the traditional approach used in Javascr ...

Retrieve the object's value by utilizing the string index in TypeScript and proceed to access it further

interface IpPatientAddressDto { ... addressSeq: number; } interface IpPatientInfoDto { ... localAddress: IpPatientAddressDto; } const originalPatient:IpPatientInfoDto = { ... localAddress:{ addressSeq:0001 } } const createAddrCollec ...

Resetting dynamic rows in Angular 6 when new ones are added

How to implement the purchase HTML form? <div class="d-flex justify-content-center align-items-center"> <div class="col-md-12 border"> <div class="card-header header-elements-inline"> <h4 class="card-title">Add Purchase ...

Using ngFormModel with Ionic 2

How can I properly bind ngFormModal in my Ionic 2 project? I am facing an issue while trying to import it on my page, resulting in the following error message: Uncaught (in promise): Template parse errors: Can't bind to 'ngFormModel' since ...

Output specification: Mandate certain attributes of a designated kind, while permitting them to be incomplete

I am searching for a solution in TypeScript that enforces the return type of a method to be a subset of an interface. Essentially, this means that all properties on the returned object must exist on the interface, but they are not required. Background: De ...

The type 'string' is not a valid index for the type 'Partial<NewData>'

Can someone help me resolve this issue? https://i.sstatic.net/GkFYf.png I am looking to encase each object field from the getters argument in a ComputedRef wrapper import { computed, ComputedRef } from "vue"; function useComputedGroup<T exte ...

Declaration in Typescript for an array of strings that will be returned as a

I am facing an issue with my async function that is supposed to return either a single string or an array of strings. Here is the relevant code snippet: async getAllAnnotationTimes(): Promise<string> | Promise<string[]> { return aw ...

Error: Certain Prisma model mappings are not being generated

In my schema.prisma file, I have noticed that some models are not generating their @@map for use in the client. model ContentFilter { id Int @id @default(autoincrement()) blurriness Float? @default(0.3) adult ...

The chaos of Typescript decorators

Are there any strategies for managing extensive decorator usage within classes? Consider this instance of a class property in my NestJS application, featuring an incomplete swagger documentation decorator: @ApiModelProperty({ description: 'des ...

Having trouble with the Angular 17 Router functionality when running on a node server

I find myself facing an unusual situation. I am currently developing a basic app that needs to navigate from the landing-page (directory '') to a form component (directory '/form') using Angular 17 and node.js with express.js. I have no ...

What is the best way to add all the items from an array to a div element?

I am currently facing an issue where only the last object in my array is being added to my div using the code below. How can I modify it to add all objects from the array to my div? ajaxHelper.processRequest((response: Array<Vehicle.Vehicle>) ...

Having trouble compiling a Vue.js application with TypeScript project references?

I'm exploring the implementation of Typescript project references to develop a Vue application within a monorepo. The current structure of my projects is outlined below: client/ package.json tsconfig.json src/ ... server/ package.json t ...

Dynamically determine the length of an array using Typescript

Can the length of an array be determined based on a numerical variable? For example: func(1); // outputs [string] func(2); // outputs [string, string] func(5); // outputs [string, string, string, string, string] ...