При запросе веб-API от Angular 4 SPA требование области действия является нулевым - PullRequest
0 голосов
/ 02 июля 2018

Я пытаюсь защитить свои веб-API с помощью Azure B2C AD и использовать веб-API с помощью Angular 4 SPA. Однако по какой-то причине заявка на область действия всегда пуста, хотя другие заявки работают нормально.

Я использую библиотеку MSAL версии 0.1.6 в приложении Angular и следую этому руководству: https://github.com/Azure-Samples/active-directory-b2c-javascript-angular2.4-spa

Это мой web api startup.auth:

public partial class Startup
{
    // These values are pulled from web.config
    public static string AadInstance = ConfigurationManager.AppSettings["ida:AadInstance"];
    public static string Tenant = ConfigurationManager.AppSettings["ida:Tenant"];
    public static string ClientId = ConfigurationManager.AppSettings["ida:ClientId"];
    public static string SignUpSignInPolicy = ConfigurationManager.AppSettings["ida:SignUpSignInPolicyId"];
    public static string DefaultPolicy = SignUpSignInPolicy;

    /*
     * Configure the authorization OWIN middleware.
     */
    public void ConfigureAuth(IAppBuilder app)
    {
        TokenValidationParameters tvps = new TokenValidationParameters
        {
            // Accept only those tokens where the audience of the token is equal to the client ID of this app
            ValidAudience = ClientId,
            AuthenticationType = Startup.DefaultPolicy
        };

        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
        {
            // This SecurityTokenProvider fetches the Azure AD B2C metadata & signing keys from the OpenIDConnect metadata endpoint
            AccessTokenFormat = new JwtFormat(tvps, new OpenIdConnectCachingSecurityTokenProvider(String.Format(AadInstance, Tenant, DefaultPolicy))),

        });
    }
}

Это мой контроллер:

[Authorize]
[EnableCors(origins: "*", headers: "*", methods: "*")] // tune to your needs
public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
        string owner = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
        var scopes = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/scope");
        return new string[] {"value1", "value2"};
    }
}

Переменная владельца содержит GUID, как и ожидалось, однако переменная scopes всегда имеет значение NULL.

Это мой auth.service.ts:

import { Injectable } from '@angular/core';
import environment from '../../../environments/environment';
import * as Msal from 'msal'

declare var bootbox: any;
// declare var Msal:any;

const B2CTodoAccessTokenKey = "b2c.api.access.token";

const tenantConfig = {
        tenant: environment.b2cTenant,
        clientID: environment.b2cClientID,
        signUpSignInPolicy: environment.b2cSignUpSignInPolicy,
        b2cScopes: environment.b2cScopes
    };

@Injectable()
export class AuthService {

    // Configure the authority for Azure AD B2C
    private authority = "https://login.microsoftonline.com/tfp/" + tenantConfig.tenant + "/" + tenantConfig.signUpSignInPolicy;

    private loggerCallback(logLevel, message, piiLoggingEnabled) {
        console.log(message);
    }    

    private logger = new Msal.Logger(this.loggerCallback, { level: Msal.LogLevel.Verbose }); 

    clientApplication = new Msal.UserAgentApplication(
        tenantConfig.clientID, 
        this.authority, 
        function(errorDesc: any, token: any, error: any, tokenType: any) {
            console.log('calling acquireTokenSilent with scopes: ' + tenantConfig.b2cScopes);
            console.log('idtoken: ' + token)
            if (token) {
                this.acquireTokenSilent(tenantConfig.b2cScopes).then(function (accessToken) {
                    // Change button to Sign Out
                    console.log('acquireTokenSilent');
                    sessionStorage.setItem("b2c.api.access.token", accessToken);
                }, function (error) {
                    console.log(error);
                    this.acquireTokenPopup(tenantConfig.b2cScopes).then(function (accessToken) {
                        console.log('acquireTokenPopup');
                        sessionStorage.setItem("b2c.api.access.token", accessToken);
                    }, function (error) {
                        console.log(error);
                    });
                });
            }
            else if (errorDesc || error) {
                console.log(error + ':' + errorDesc);
            }
        },
        { 
            logger: this.logger,
        });

    loginRedirect(): void {
        console.log('scopes: ' + tenantConfig.b2cScopes);
        this.clientApplication.loginRedirect(tenantConfig.b2cScopes);
    }

    login() : void {
        var _this = this;
        this.clientApplication.loginPopup(tenantConfig.b2cScopes).then(function (idToken: any) {
            _this.clientApplication.acquireTokenSilent(tenantConfig.b2cScopes).then(
                function (accessToken: any) {
                    _this.saveAccessTokenToCache(accessToken);
                }, function (error: any) {
                    _this.clientApplication.acquireTokenPopup(tenantConfig.b2cScopes).then(
                        function (accessToken: any) {
                            _this.saveAccessTokenToCache(accessToken);
                        }, function (error: any) {
                            //bootbox.alert("Error acquiring the popup:\n" + error);
                            console.log("Error acquiring the popup:\n" + error)
                        });
                })
        }, function (error: any) {
            //bootbox.alert("Error during login:\n" + error);
            console.log("Error during login:\n" + error);
        });
    }

    getTokenFromCache() : string {
        return sessionStorage.getItem(B2CTodoAccessTokenKey);
    }

    saveAccessTokenToCache(accessToken: string): void {
        sessionStorage.setItem(B2CTodoAccessTokenKey, accessToken);
    }

    logout(): void{
        this.clientApplication.logout();
    }

    isLoggedIn(): boolean {        
        var user = this.clientApplication.getUser();

        console.log('isLogged In: ' + (user != null));        
        console.log('token in cache ' + (this.getTokenFromCache() != null))
        //console.log('token: ' + this.getTokenFromCache());
        return this.clientApplication.getUser() != null && this.getTokenFromCache() != null; 

    }
}

Наконец, это мои значения окружения:

export default {
    b2cTenant: "[tenant].onmicrosoft.com",
    b2cClientID: '[app-id]',
    b2cSignUpSignInPolicy: "[policy]",
    b2cScopes: ["https://[tenant].onmicrosoft.com/apidemo/read", "https://[tenant].onmicrosoft.com/apidemo/user_impersonation"]
};

Вот изображения настройки Azure:

Свойства API: API properties

API опубликованные области: API published scopes

Доступ к клиентскому API: Client API access

Почему значение переменной scopes равно NULL? Что я упустил? Переменная владельца содержит значение!

С уважением

Ответы [ 2 ]

0 голосов
/ 08 августа 2018

Решено с помощью другой клиентской библиотеки: https://github.com/damienbod/angular-auth-oidc-client

В случае, если кто-нибудь отправит решение, используя библиотеку MSAL, я, конечно, отмечу его как решение

0 голосов
/ 04 августа 2018

Попробуйте запустить Fiddler, чтобы увидеть, что происходит.

  1. Вам может потребоваться определить пользователей и роли для достижения этой цели. См. это руководство .
  2. Один из ваших параметров конфигурации может не соответствовать тому, что вы указали при регистрации приложения. Убедитесь, что ClientID / AppID совпадают во всех случаях.
  3. Убедитесь, что URL-адреса ответов в вашем коде совпадают с теми, которые вы указали при регистрации приложения.

Пожалуйста, посмотрите, если эта проблема относится к вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...