Почему MSAL loginPopup отвечает «клиент приложения запросил область, которой нет в ресурсе»? - PullRequest
0 голосов
/ 09 июля 2019

(продолжение вопроса: Почему мой SPA, который вызывает мой WebAPI, использует Azure Active Directory и получает сообщение "В этом запросе отказано в авторизации."? )

Мойклиент SPA пытается вызвать защищенный WebAPI (сервис).Клиент использует MSAL (библиотеки аутентификации Micosoft).Проблема возникает до вызова API, то есть на рисунке ниже где-то между 1 и 2.

enter image description here

Вот клиент

<!DOCTYPE html>
<html>
<head>
    <title>Quickstart for MSAL JS</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.4/bluebird.min.js"></script>
    <script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.2/js/msal.js"></script>
</head>
<body>
    <div class="container">
        <div>
            <button id="GetTodos" onclick="getTodos()">Get Todos</button>
        </div>
    </div>
    <script>

        var msalConfig = {
            auth: {
                clientId: 'xxxxxxxxxxxxxxxxxxxxxxx2427', 
                authority: "https://login.microsoftonline.com/my.tenant"
            },
            cache: {
                cacheLocation: "sessionStorage",
                storeAuthStateInCookie: true
            }
        };


        var requestObj = {
            // scopes: ["user.read"]
            scopes: ["access_as_user"]
        };

        var myMSALObj = new Msal.UserAgentApplication(msalConfig);

        myMSALObj.handleRedirectCallback(authRedirectCallBack);

        function getTodos() {
            console.log("getTodos ...");

            myMSALObj.loginPopup(requestObj)
                .then(response => {
                    myMSALObj.acquireTokenPopup(requestObj).then(function (tokenResponse) {

                        var xmlHttp = new XMLHttpRequest();
                        xmlHttp.onreadystatechange = function () {
                            if (this.readyState == 4 && this.status == 200) {
                                console.log("success");
                                //this.responseText
                            } else {
                                console.log("failure");
                            }
                        }
                        const apiUrl = "https://localhost:44321/api/todolist";
                        xmlHttp.open("GET", apiUrl, true); // true for asynchronous
                        xmlHttp.setRequestHeader('Authorization', 'Bearer ' + tokenResponse.accessToken);
                        xmlHttp.send();

                    }).catch(function (error) {
                        console.log(error);
                    });
                })
                .catch(err => {
                    // handle error
                    console.log("login popup failed.", err);
                });
        }


        function authRedirectCallBack(error, response) {
            console.log('authRedirectCallBack');
            if (error) {
                console.log(error);
            } else {
                if (response.tokenType === "access_token") {
                    console.log("response.tokenType === access_token");
                } else {
                    console.log("token type is:" + response.tokenType);
                }
            }
        }

    </script>
</body>
</html>

И клиент, и служба являются зарегистрированными приложениями в Azure Active Directory

enter image description here

Клиент имеет разрешения API для доступа к службе.

enter image description here

И сервис предоставляет API с областью доступа access_as_user

enter image description here

Однако вызов

myMSALObj.loginPopup(requestObj)

вызывает

ServerError: "AADSTS650053: The application 'ClientSPA' asked for scope 'access_as_user' that doesn't exist on the resource '00000003-0000-0000-c000-000000000000'.

И при использовании Chrome я получаю это сообщение

enter image description here

Дальнейшее расследование

Вместо того, чтобы запрашивать область действия «access_as_user», я спрашиваю «user.read». Это дает мне токен доступа.Но это заставляет WebAPI отвечать

Authorization has been denied for this request

И когда я декодирую токен доступа, я вижу, что аудитория равна https://graph.microsoft.com. Но я ожидаю, что аудитория будет «* 1059».* См. Рисунок ниже (запутанные строки содержат информацию, относящуюся к моему пользователю и моему зарегистрированному приложению)

enter image description here

Вопросы

  1. Откуда берется идентификатор ресурса '00000003-0000-0000-c000-000000000000' (упоминается в сообщении об ошибке)?Это не идентификатор приложения ни клиента, ни сервиса.

  2. Что я сделал неправильно, либо в конфигурации в Azure Active Directory, либо в клиенте?

  3. Может ли CORS быть проблемой?Я настроил службу, чтобы разрешить CORS.

1 Ответ

1 голос
/ 10 июля 2019

Область действия должна включать идентификатор ресурса (URI идентификатора приложения). Вы можете найти полное значение, перейдя в «Выставить API» -> Изменить область действия -> Скопировать метку вверху ...

var requestObj = {
    // scopes: ["https://graph.microsoft.com/user.read"]
    scopes: ["https://ServiceWebAPI/TodoListService-NativeDotNet-access_as_user"]
};

Дополнительная информация по отдельным областям применения здесь: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#requesting-individual-user-consent

...