ASP.NET Core 2.0 Web API Azure Ad v2令牌授权不起作用 [英] ASP.NET Core 2.0 Web API Azure Ad v2 Token Authorization not working

查看:134
本文介绍了ASP.NET Core 2.0 Web API Azure Ad v2令牌授权不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用ASP.NET Core 2.0创建一个Web API服务器,该服务器使用azure ad v2端点令牌授权.我也有一个Angular 2应用程序,可在该应用程序中登录office365.我从那里得到一个令牌,然后向Web API服务器中的授权操作发送一个简单的请求.但是,我的令牌未通过授权检查,并且收到401未经授权的响应.提供的描述是:

I am trying to create a Web API server using ASP.NET Core 2.0 which uses azure ad v2 endpoint token authorization. I also have an Angular 2 app where the office365 login happens. I get a token from there and then send a simple request to an authorized action in the Web API server. However my token doesn't pass the authorization checks and I get a 401 Unauthorized response. The description provided is:

bearer error ="invalid_token",error_description =未找到签名密钥"

Bearer error="invalid_token", error_description="The signature key was not found"

我对令牌进行了解码,并且解码器也引发了无效的签名错误.这是我用于配置和令牌授权的代码的重要部分:

I decoded the token and the decoder throws an invalid signature error as well. Here are the important parts of my code I use for configuration and token authorization:

Web API服务器:

appsettings.json

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "ClientId": "my-registered-app-client-id",
  },
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  }
}

AzureAdAuthenticationBuilderExtensions.cs

public static class AzureAdServiceCollectionExtensions
{
    public static AuthenticationBuilder AddAzureAdBearer(this AuthenticationBuilder builder)
        => builder.AddAzureAdBearer(_ => { });

    public static AuthenticationBuilder AddAzureAdBearer(this AuthenticationBuilder builder, Action<AzureAdOptions> configureOptions)
    {
        builder.Services.Configure(configureOptions);
        builder.Services.AddSingleton<IConfigureOptions<JwtBearerOptions>, ConfigureAzureOptions>();
        builder.AddJwtBearer();
        return builder;
    }

    private class ConfigureAzureOptions: IConfigureNamedOptions<JwtBearerOptions>
    {
        private readonly AzureAdOptions _azureOptions;

        public ConfigureAzureOptions(IOptions<AzureAdOptions> azureOptions)
        {
            _azureOptions = azureOptions.Value;
        }

        public void Configure(string name, JwtBearerOptions options)
        {
            options.Audience = _azureOptions.ClientId;
            options.Authority = $"{_azureOptions.Instance}common/v2.0";

            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = false,
            };
        }

        public void Configure(JwtBearerOptions options)
        {
            Configure(Options.DefaultName, options);
        }
    }
}

Startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(sharedOptions =>
        {
            sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddAzureAdBearer(options => Configuration.Bind("AzureAd", options));

        services.AddMvc();
        services.AddCors(options =>
        {
            options.AddPolicy("AllowAllOrigins",
             builder =>
             {
                 builder.AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
             });
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseCors("AllowAllOrigins");

        app.UseAuthentication();
        app.UseMvc();
    }
}

现在这是我在Angular2应用中用于身份验证的代码:

import { Injectable } from '@angular/core';
import { Headers } from '@angular/http';
import * as hello from 'hellojs/dist/hello.all.js';

import * as MicrosoftGraph from "@microsoft/microsoft-graph-types";
import * as MicrosoftGraphClient from "@microsoft/microsoft-graph-client";
import { Configs } from "../../../shared/configs"

@Injectable()
export class HttpService {
  url = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=${Configs.appId}&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F&response_mode=query&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fmail.read&state=12345`;

  getAccessToken() {
    const msft = hello('msft').getAuthResponse();
    const accessToken = msft.access_token;
    return accessToken;
  }


  getClient(): MicrosoftGraphClient.Client
  {
    var client = MicrosoftGraphClient.Client.init({
      authProvider: (done) => {
          done(null, this.getAccessToken()); //first parameter takes an error if you can't get an access token
      },
      defaultVersion: 'v2.0'
    });
    return client;
  }
}

从端点返回令牌时,我向Web API服务器上的有效端点发送了一个请求.

When a token is returned from the endpoint I send a request to a valid endpoint on my Web API server.

重要说明:我在Web API和Angular应用程序中都使用了相同的AppId,因为AzureAd v2.0终结点需要它.

我的意思是,我认为我正在按照书来做所有事情,但是显然缺少一些东西.如果有人能告诉我我在配置中做错了什么,我将无比感激!

My point is that I think I'm doing everything by the book but there is obviously something missing. If anyone could tell me what I did wrong in my configuration, I'd be immeasurably grateful!

aud属性为:

https://graph.microsoft.com

推荐答案

在评论中进行了不那么简短的讨论后,问题得以解决.

After a not-so-short discussion in the comments the issue was resolved.

讨论的重点:

  • The access token contained an aud claim with the value of https://graph.microsoft.com, which means the token is meant for the Microsoft Graph API, not their API
  • A Web API needed to be registered at https://apps.dev.microsoft.com/, after which the app needed to ask for an access token using a scope similar to: api://25f66106-edd6-4724-ae6f-3a204cfd9f63/access_as_user

因此,请确保aud声明包含您的API的客户端ID或应用ID URI.这意味着它适用于您的API.

So make sure that the aud claim contains the client ID or app ID URI for your API. That means it is meant for your API.

令牌还需要包含必要的范围.

The token also needs to contain the necessary scopes.

从AAD请求访问令牌时,请确保指定正确的范围.

When asking for an access token from AAD, make sure you specify the correct scopes.

此外,如果您使用的是v1端点,请确保使用ADAL,而不是MSAL.在v1中,也必须使用resource(而不是范围),resource的值必须设置为API的客户端ID或应用ID URI.

Also, if you are using the v1 endpoints, make sure to use ADAL, not MSAL. In v1 also instead of scope, you have to use resource, which must have a value set to either the client ID or app ID URI of the API.

这篇关于ASP.NET Core 2.0 Web API Azure Ad v2令牌授权不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆