繁体   English   中英

使用Azure AD的API后端(.NET Core)中的身份验证基础

[英]Authentication basics in API Backend (.NET Core) using Azure AD

也许这个问题比标题更全面。 关于身份验证,令牌,JWT,Azure AD等的文章很多,但是所有这些文章似乎都讲述了一个不同的故事,至少对于我来说,这使基本概念不清楚。 我将尝试使用我的案例来解释我的问题。

我已经用Visual代码中的React构建了一个前端应用程序,并在Visual Studio .Net Core 2(Web API)中构建了一个后端应用程序。 该应用程序托管在Azure中,我们希望使用Azure AD进行身份验证。

前端使用Adal-React( https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-libraries )和Axios( https://github.com/axios/ axios )。
在教程的帮助下,我已经使用Azure环境中列出的TenantID和ClientID在前端和API(后端)中设置了配置。

尽管我已经设置好并且可以正常工作,但是我对它的工作方式还是不太了解。

我将尝试解释应用程序中当前的工作流程,并在下面列出我当前的问题:

1-用户导航到前端应用程序,adal检查用户是否已通过身份验证,如果不是,则将该人重定向到我们的azure登录环境,这在adal配置(前端)中进行如下设置:

  const adalConfig = {
         tenant: 'vhsprod.onmicrosoft.com',
         clientId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx',
         endpoints: {
          api: 'https://xxxxx.onmicrosoft.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx (client id)',
         },
         postLogoutRedirectUri: window.location.origin,
         redirectUri: 'http://localhost:3000/user-form',
         cacheLocation: 'sessionStorage'
        };
        export const authContext = new AuthenticationContext(adalConfig);
        export const getToken = () => {
         return authContext.getCachedToken(authContext.config.clientId);
        };

2-用户需要登录,并且正在检查用户是否存在于Azure AD环境中(如果存在),则该用户将被重定向回到前端,并且我们获得了自己的令牌

3-用户在前端打开一个需要从后端获取数据的表单/页面,使用刚刚接收到的令牌进行API调用。 呼叫是使用前端中的Axios完成的,并且还配置了Axios:

export const axiosCallToMyAPI = axios.create({
  baseURL: 'http://localhost:52860/api/',
  timeout: 5000,
  headers: {'Authorization': 'Bearer ' + initialToken}
});

最初的令牌是从Adal收到的,我们刚刚收到的令牌是:

let initialToken = sessionStorage.getItem('adal.idtoken')

4-正在对API进行调用,在这里我们还设置了使用Azure AD的配置( appsettings.json ):

"AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantDomain": "xxxx.onmicrosoft.com",
    "TenantId": "xxxx.onmicrosoft.com",
    "ClientId": "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx"
  }

5-在API的启动类中,正在验证令牌:

services
                .AddAuthentication(sharedOptions =>
                {
                    sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                    sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 
                    sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 
                })
                .AddJwtBearer(options =>
                {
                    options.Audience = this.Configuration["AzureAd:ClientId"];
                    options.Authority = $"{this.Configuration["AzureAd:Instance"]}{this.Configuration["AzureAd:TenantId"]}";

                    options.Events = new JwtBearerEvents()
                    {

                        OnTokenValidated = context =>
                        {
                            return Task.CompletedTask;
                        }
                    };
                });

我剩下的问题和所作的假设(阅读几篇文章)如下:

  • 使用前端接收到的Azure令牌对API进行调用,API如何知道此令牌为“有效”? 我知道API的启动类使用事件OnTokenValidated但这背后的魔术是什么? 纯粹是使用接收到的令牌来检查appsettings配置的租户/客户端ID吗?
  • 在几篇文章中,他们使用/提到了SecretKey / Signing Key,但在我的示例中,我尚未实现SecretKey,但仍然可以使用。 我需要在我的API(后端)中实现秘密/签名密钥吗? 有必要吗?
  • 我还阅读了隐式流,OpenID connect和其他一些术语。 当像在我的示例中那样使用Azure AD身份验证并以这种方式进行操作时,我是否会使用openid connect自动执行implicit flow (前端->后端)和身份验证? 换句话说,使用Azure身份验证时,您是否会自动执行这些/最佳做法,还是应该实施它?
  • 令牌具有某些声明。 定义了由Azure提供的范围(您还可以在其中设置这些声明,例如电子邮件和角色),但是当使用AspNet(身份)时,还可以向当前令牌/会话添加自己的声明,例如,当我添加角色声明时从aspnetidentity到我的令牌。 这些声明与原始声明(still bearer / jwt?)有什么不同?这是一种好的做法吗?

谁能确认/解释这些问题?

如果这个故事有点笼统,我深表歉意,但目前我们的试错率很高,我只是想解决问题。

使用前端接收到的Azure令牌对API进行调用,API如何知道此令牌为“有效”? 我知道API的启动类使用事件OnTokenValidated,但这背后的魔力是什么? 纯粹是使用接收到的令牌来检查appsettings中配置的租户/客户端ID吗?

您在配置身份验证时指定了授权。 验证处理程序在应用程序启动时从如下所示的URL下载OpenId Connect元数据: https : //login.microsoftonline.com/joonasapps.onmicrosoft.com/.well-known/openid-configuration

从那里获取公共签名密钥和有效的发行者URI。

处理程序针对获得的签名密钥检查令牌的数字签名是否有效,发行者是否有效,受众是否有效以及令牌是否过期。

在几篇文章中,他们使用/提到了SecretKey / Signing Key,但在我的示例中,我尚未实现SecretKey,但仍然可以使用。 我需要在我的API(后端)中实现秘密/签名密钥吗? 有必要吗?

检查上面。

我还阅读了隐式流,OpenID connect和其他一些术语。 当像我的示例一样使用Azure AD身份验证并以这种方式进行操作时,我是否会自动执行隐式流(前端->后端)和使用openid connect进行身份验证? 换句话说,使用Azure身份验证时,您是否会自动执行这些/最佳做法,还是应该实施它?

隐式流程意味着客户端可以直接从授权端点获取访问令牌,而不是从令牌端点请求访问令牌。 单页应用将其与隐藏的iframe结合使用以获取访问令牌并刷新过期的令牌。 它确实取决于用户的会话,而Azure AD保持活动状态。 如果您拥有更“经典”的后端应用程序,则可能会使用授权代码流而不是隐式流。

令牌具有某些声明。 定义了由Azure提供的范围(您还可以在其中设置这些声明,例如电子邮件和角色),但是当使用AspNet(身份)时,还可以向当前令牌/会话添加自己的声明,例如,当我添加角色声明时从aspnetidentity到我的令牌。 这些声明与原始声明(still bearer / jwt?)有什么不同?这是一种好的做法吗?

您的应用无法修改Azure AD令牌,期限。 如果您对其进行了修改,则其签名将不再有效。 而是,ASP.NET Core Identity使用Cookie +会话来存储已登录用户的声明。 因此,最终的用户会话将包含令牌的声明以及您在用户存储中的声明。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM