也许这个问题比标题更全面。有很多关于身份验证、令牌、JWT、Azure AD等的帖子,但所有这些帖子似乎都在讲述不同的故事,这使得基本概念对我来说有点不清楚。我将尝试使用我的案例来解释我的问题。
我用React在Visual Studio Code中构建了一个前端应用程序,在Visual Studio .Net Core 2(Web API)中构建了一个后端应用程序。这些应用程序正在Azure中托管,我们想要使用Azure AD进行身份验证。
前端使用Adal-React (https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-libraries)和Axios (https://github.com/axios/axios)。
在教程的帮助下,我已经在前端和API(后端)中设置了配置,主要是使用在Azure环境中列出的TenantID和ClientID。
虽然我已经设置好并且它正在工作,但它的工作方式对我来说还不太清楚。
我用React在Visual Studio Code中构建了一个前端应用程序,在Visual Studio .Net Core 2(Web API)中构建了一个后端应用程序。这些应用程序正在Azure中托管,我们想要使用Azure AD进行身份验证。
前端使用Adal-React (https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-libraries)和Axios (https://github.com/axios/axios)。
在教程的帮助下,我已经在前端和API(后端)中设置了配置,主要是使用在Azure环境中列出的TenantID和ClientID。
虽然我已经设置好并且它正在工作,但它的工作方式对我来说还不太清楚。
我会尝试解释一下我的应用程序中当前的工作流程,并列出我目前的问题:
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连接和一些其他术语。像在我的例子中使用Azure AD身份验证这样做时,我是否自动执行了
implicit flow
(前端-->后端)和使用openid connect
进行身份验证?换句话说,当使用Azure身份验证时,您是否自动执行这些/最佳实践,还是应该自己实现? - 令牌具有特定的声明/范围定义,这些声明由Azure提供(您也可以设置这些声明,如电子邮件和角色),但是当使用AspNet(Identity)时,您还可以将自己的声明添加到当前令牌/会话中,例如当我从aspnetidentity向我的令牌添加角色声明时。这些声明与原始声明有何不同(仍然是承载者/jwt?),这是一个好的实践方法吗?
请问是否有人能够确认/解释这些问题?
如果我的故事有点笼统,我很抱歉,但目前我们的试错率太高了,我只是想澄清一些事情。
要验证正在使用哪个流程以及是否正在接收,请检查发送到AAD的URL请求中由ADAL设置的以下参数:
参考:https://preview.tinyurl.com/yaqatsua
response_type
决定的。如果设置为code
,它将使用授权码流程。如果是token
或id_token
,则使用隐式流程。如果两者都组合在一起,则使用混合流程 :) 接下来还有后端流程... - juunas