I am trying to obtain a token in React using MSAL-Browser. With the following code, I encounter the following error when reaching "await this.publicClientApplication.loginPopup": "AADSTS900561: The endpoint only accepts POST, OPTIONS requests. Received a GET request." Unfortunately, I couldn't find much information about this specific issue.

My problem is that I cannot receive a response in order to request a token. To request a token, I need, among other things, the "code." Does anyone have an idea of what might be causing this issue?

I have also attempted to set up an HTTP server to handle the response from MSAL. However, as soon as I log in, the URL "http://localhost:65192/#code=long_code_text_here&client_info=long_client_id_here&session_state=some_session_state_here&" is sent to the HTTP server, and with the "#" character, nothing is received. This prevents me from even processing the "code." As seen in the code, I have set the "response_mode" to "query" to use "?" instead of "#," but it appears that for MSAL-Browser, or specifically for loginPopup and loginRedirect, "response_mode = fragment" is static. Any ideas?

Edit: I do not have access to Azure AD, but I already have a Python solution running locally on my computer that obtains the token.

import React, { Component } from 'react';
import './App.css';
import SelectionManager from "./SelectionManager";
import {config} from "./Config";
import {PublicClientApplication} from "@azure/msal-browser";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            error: null,
            isAuthenticated: false,
            user: {},
        };
        this.login = this.login.bind(this);
        // Initialize the MSAL application object
        this.publicClientApplication = new PublicClientApplication({
            auth: {
                clientId: config.clientId,
                redirectUri: config.redirectUri,
                authority: config.authority,
                response_type: config.response_type,
                response_mode: "query"
            },
            cache: {
                cacheLocation: "sessionStorage",
                storeAuthStateInCookie: false
            }
        });

        this.publicClientApplication.initialize();
        console.log("initialized");
    }

    async login() {
        console.log("logging in");
        try {
            console.log("try to open popup");

            const response = await this.publicClientApplication.loginPopup({
                scopes: config.scopes,
                prompt: "select_account"
            });

            console.log("popup may have been opened");
            this.setState({ isAuthenticated: true });
        }
        catch (err) {
            this.setState({
                isAuthenticated: false,
                user: {},
                error: err
            });
        }
    }

    render() {
        return (
            <div className="App">
                {this.state.isAuthenticated ? <p>
                <SelectionManager/>
                </p>:
                    <p>
                        <button onClick={() => this.login()}> Login</button>
                    </p>
                }
            </div>
        );
    }
}

export default App;

1

There are 1 answers

0
SaiVamshiKrishna On

You have set the response_mode to "query". This is the correct setting for using the response_type "code". However, the loginPopup method does not support the "query" response mode.

Use the acquireTokenPopup method instead of the loginPopup method. The acquireTokenPopup method supports both the "query" and "fragment" response modes.

Here is the code i have tried:

    // src/AuthButton.js
  
    import  React, { useEffect, useState } from  "react";
    import { PublicClientApplication } from  "@azure/msal-browser";
    import  msalConfig  from  "./msalConfig";
    
    const  AuthButton  = () => {
    const [publicClientApplication, setPublicClientApplication] =  useState(null);
    useEffect(() => {
    const  initializeMsal  =  async () => {
    const  pca  =  new  PublicClientApplication(msalConfig);
    await  pca.initialize();
    setPublicClientApplication(pca); 
    }; 
    initializeMsal();   
    }, []);
    

    const  handleLogin  =  async () => {
    try {
    const  loginRequest  = {
    scopes: ["openid", "profile", "user.read"],
    };
    const  loginResponse  =  await  publicClientApplication.acquireTokenPopup(loginRequest);
    console.log("Access token:", loginResponse.accessToken); 
    } 
    catch (error) {
    console.error("Authentication error:", error);
    }   
    };
    
    return (  
    <div>
    <button  onClick={handleLogin}>Login</button>
    </div>
    );
    };

    export  default  AuthButton;

Result enter image description here