如何使用Open Id Connect在.net Core 2.2 API中使用令牌验证请求

问题描述

我有一个.net core 2.2 api安装程序,并已部署到Azure。我已使用OpenId Connect通过以下代码使用azure活动目录单tenenat处理身份验证。还有我控制器上的Authorize装饰器。一切正常,当我浏览到我的Azure部署api(myappname.azurewebsites.net)时,我得到了Microsoft登录提示。然后,我可以登录并查看我的路线数据。

        services.AddAuthentication(auth =>
        {
            auth.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            auth.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            auth.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
        .AddCookie()
        .AddOpenIdConnect(opts =>
        {
            Configuration.GetSection("OpenIdConnect").Bind(opts);
            opts.Events = new OpenIdConnectEvents
            {
                OnAuthorizationCodeReceived = ctx =>
                {
                    return Task.CompletedTask;
                }
            };
            opts.Scope.Add("openid");
            opts.Scope.Add("profile");
            opts.Scope.Add("access_as_user");
        });

问题是当我为控制器打开授权时,无法从我的角度SPA客户端应用程序中调用它。我已经成功配置了MSAL,并且我的api调用正在传递令牌。但是,出现以下错误

https://login.microsoftonline.com/bit4f574-5968-4a40-049d-1c0dc2ca0513/oauth2/authorize?client_id=caor847f-dd19-4489-bef7-684803728c665&redirect_uri=https%3A%2F%2Fmyapi.azurewebsites.net%2Fsignin-oidc&response_type=code%20id_token&scope=openid%20profile%20user_access&response_mode=form_post&nonce=637373859487758409.MzhhYTAoeiudtMTdlNS00NzgxLWJjMTQtNzM1YWE3NsdlkelasdNGYxMmQtMjZmYS00YmI2LTgwY2UtNDEwMTNhMWNkN2Zi&state=CfDJ8KCu3Hr4UOhLjOspjLNEh0VtJd4GNXqwdibjSiZf7FpUJOL0EDlFso0g0s_iOZHDNbP2aiHVfdzqJSmHkesd-bMjP6ThYva6AfZBa8UZcnGcwgo2ldlg4Fx9vmNVDuSlvHyTlHkd8yNndslkgoyHtfM4RMXamq1wny1J39BZRRATn1RdAsgalgKP_QkxLaDCwgvdzjp3dKls5UVQE1j7MD6bcKR__1-VmfVKhROn1coQh7OJrea6Jni4jdV7e0wv70TVprGtseJFg8fyHg3KKW14xeX2orlkgls5aLe1uG0c5ehlapFXBirBSgFU3uqOWw0_iLeJUbTL8-HPooixynQRWe1WoiLnQuFYUu7Lx-usdlglvM4WvLfAyTZ5uQY_KsOtr08MxWRlQ5HHVk8Moe1k_N_3BCz8sdkgowwZEKsgiKd_iwcXgzxmgg&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.3.0.0

我该如何解决?看来我的api正在将客户端请求重定向到microsoft登录名,但是我认为这应该起作用的方式是我的api应该验证请求或范围中的令牌并授予访问权限,而无需将请求重定向登录名。

解决方法

此处的关键点是将SPA OAuth与API OAuth完全分开,具有以下行为:

  • SPA进行重定向处理并从授权服务器获取令牌-此代码基于Javascript,不需要C#“网络后端”
  • API通过授权服务器的令牌签名公钥验证令牌-此代码基于C#,这是API开发的一种好语言
  • Authorization Server是一个开箱即用的组件,例如Azure AD,并且您从来没有自己编写JWT的代码(很高兴看到您已经这样做了)

我见过许多在线文章,这些问题混杂在一起,对于OAuth技术的新手可能会造成很大的困扰。因此,重要的是要清楚最终解决方案中想要的东西。

API OAUTH密码

默认情况下,您的C#代码仅需要几行,从添加这样的程序包开始:

<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.8" />

用于配置API安全性的代码将如下所示。请注意,此处与OpenIdConnect /网络行为无关。

private void ConfigureOAuthTokenValidation(IServiceCollection services)
{
    services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options => {
                    options.Authority = "https://login.microsoftonline.com/mytenantid";
                    options.Audience = "api://default";
                });

真实世界样本

我的.Net Core API解决方案有一些有趣的地方。这些示例相当先进,但是使您能够运行可一起使用的本地API和SPA。

目标是使API和SPA都获得最佳的最终结果,因此上述链接可能会帮助您考虑您的情况。