获取访问令牌以从我的 ASP.NET Core 5 MVC 网络应用程序调用 API

Getting access token to call an API from my ASP.NET Core 5 MVC web app

我正在努力思考如何在我的 ASP.NET Core 5 应用程序中使用 Azure Active Directory 和 OpenID Connect 正确验证用户身份,并获得必要的访问令牌以便我可以发出 REST 请求到 API.

我在 Azure AD 中有两个应用程序注册:

在我的 ASP.NET Core 5 MVC 应用程序中,我在启动时设置了 OpenID Connect:

        services.AddAuthentication(options =>
            {
                options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddCookie()
            .AddOpenIdConnect(options =>
            {
                options.SignInScheme = "Cookies";
                options.Authority = Configuration["AzureAdConfig:Authority"];
                options.RequireHttpsMetadata = true;
                options.ClientId = Configuration["AzureAdConfig:ClientId"];
                options.ClientSecret = Configuration["AzureAdConfig:ClientSecret"];
                // options.GetClaimsFromUserInfoEndpoint = true;
                options.ResponseType = OpenIdConnectResponseType.Code;
                options.UsePkce = true;
                options.Scope.Add("offline_access");
                options.Scope.Add("profile");
                options.Scope.Add("api://e968735b-d85e-4359-b364-a9637e4a920d/myapi.data.api");
                options.SaveTokens = true;
            });

这似乎有效 - 我绝对可以在家庭控制器的 Index 方法中访问我的经过身份验证的用户,并且我看到了所有常见的预期用户声明 - 但我没有看到任何访问令牌可以调用“我的API”。

在我的 MVC 应用程序中,我有一个 class 来访问 API,它使用 HttpClient - 像这样:

HttpClient _httpClient = new HttpClient();
_httpClient.BaseAddress = new Uri(baseUrl);

_httpClient.DefaultRequestHeaders.Clear();
_httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
// but where and how can I get this access token I need to call "MyApi" ? 
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

我似乎无法弄清楚如何从原始的 OpenID Connect 调用或其他方式获取访问令牌,以便将 Bearer (token) 身份验证令牌提供给 HttpClient 打那些电话。

有什么想法吗?我已经研究了很多博客 post,而且很多都有过时的信息,这使得很难找到正确的、最新的和有效的指导....

更新

我尝试了 Tore 的回答,但首先我得到一个错误:

Exception: Correlation failed.
Unknown location

Exception: An error was encountered while handling the remote login. Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync()

这似乎是因为我没有在我的 OIDC 选项中指定 CallbackPath

现在我这样做了:

options.CallbackPath = "/localhost:51233/signin-oidc";

即使 完全 匹配我的 Azure 应用程序注册中定义的“重定向 URL”之一:

现在我收到 这个 错误:

AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application: '

也尝试过 https://localhost:51233... 但这没有任何区别。 还有其他想法吗?

要调用 API,您可以使用:

var accessToken = await HttpContext.GetTokenAsync("access_token");

var authheader = new AuthenticationHeaderValue("Bearer", accessToken);


var client = new HttpClient();


var authheader = new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Authorization = authheader;

var content = await client.GetStringAsync("https://localhost:7001/api/payment");

ViewBag.Json = JObject.Parse(content).ToString();
return View();

使用options.SaveTokens = true; (在 AddOpenIDConnect 中)会将所有令牌保存在用户 cookie 中,然后您可以使用以下方式访问它:

var accessToken = await HttpContext.GetTokenAsync("access_token");

Sample code to get all the tokens if provided:

            ViewBag.access_token = HttpContext.GetTokenAsync("access_token").Result;
            ViewBag.id_token = HttpContext.GetTokenAsync("id_token").Result;
            ViewBag.refresh_token = HttpContext.GetTokenAsync("refresh_token").Result;
            ViewBag.token_type = HttpContext.GetTokenAsync("token_type").Result;    //Bearer
            ViewBag.expires_at = HttpContext.GetTokenAsync("expires_at").Result;    // "2021-02-01T10:58:28.0000000+00:00"

您使用的是 HTTPS 吗?那么您可能会遇到问题,因为如果 HTTPS 在您的应用程序外部终止,则您在 public 互联网上使用 运行 HTTPS,但在内部您使用 HTTP。我通常将我的应用程序托管为 Azure 容器实例,因为这样我就可以将 HTTPS 流量直接发送到我的 container/application.

我想我知道答案了,而且很简单!这个错误我犯过太多次了,所以我完全理解。

注意你写的,绿色墨水包围的端口是51233,但后来你有51223,最后一个显然是行不通的,因为不匹配。

此外,它说 'implicit grant settings enabled',这实际上是另一个错误。在这种情况下,您必须考虑在客户端

中设置另一个不同的流程,如 https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow 所示