简体   繁体   中英

How to get a valid access token for a custom Azure App API? (MSAL.js)

I am trying to build a small web app which shows me my name, my schedule and my grades for school.

My school mostly uses the services from Microsoft, which gave me the idea to use their Azure API endpoints (for the schedules and grades) in my project.

I have access to create an app registration in the Azure-portal, so I did that and got it working to login with my student email. Also I tried to fetch the Microsoft Graph API and that works absolutely great.

However, when I try to fetch the Grades endpoint, it returns a 401 Unauthorized error. I'm guessing this has to do with the scopes, but I'm not sure. It turns out that my access token isn't valid for those API endpoints.

So my question is, how do I get an access token that IS valid for those API's? Or is it even possible? Keep in mind that they're separate App registrations in the Azure-portal, and that I can only edit my own one, not the one of my school.

Here is my JavaScript file, with some comments:

const config = {
    auth: {
        clientId: "my_client_id_is_here",
        authority: "https://login.microsoftonline.com/my_tenant_id_is_here",
        redirectUri: "localhost"
    }
};

async function login() {

    console.log("Started..")

    var client = new Msal.UserAgentApplication(config);

    var request = {
        scopes: [ 'User.Read' ]
    };

    let loginResponse = await client.loginPopup(request);
    console.dir(loginResponse);

    let tokenResponse = await client.acquireTokenSilent(request);
    console.dir(tokenResponse);

    // User REQUEST - Here I fetch the Graph API for some profile information, which works fine and writes it to the HTML perfectly.

    let req = await fetch("https://graph.microsoft.com/v1.0/me/", {
        headers: {
            "Authorization": "Bearer " + tokenResponse.accessToken
        }
    });

    let json = await req.json();

    console.log(json);

    document.write("Logged in as " + json.displayName);
    document.write("<br>" + json.mail);
    document.write("<br>" + json.jobTitle + " " + json.officeLocation);

    // School Grades REQUEST - this is the part where I'm trying to fetch my School Grades, but it's not working since it gives me a 401 error..
    
    let gradesReq = await fetch("https://myschool.azurewebsites.net/API/Grades/GetGrades", {
        "headers": {
          "authorization": "Bearer " + tokenResponse.accessToken
        }
    });

    try {
        let gradesJson = await gradesReq.json();
        console.log(gradesJson);
    } catch (err) {
        document.write("An error occured while trying to get the school grades..")
    }
}```

You're correct in your thinking. The reason you're getting this error is because you're using the access token acquired for a different scope ( User.Read ) with your API.

Fix is rather simple.

What you have to do is protect your API with Azure AD first. You may find this link helpful in implementing this functionality: https://docs.microsoft.com/en-us/azure/active-directory/develop/scenario-protected-web-api-overview .

Once you have done that, all you need to do then is to acquire token for your API. In that case, your scopes code will be something like the following:

var request = {
    scopes: [ 'api://<your-application-id>/.default' ]
};

Once you acquire the token for this scope and use it with your API, you should not get 401 exception that you're getting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM