Signalr 信号器Azure令牌的Web Api不工作
我有一个Asp.NETWebAPI(Api1),需要将消息发送到SignalrRealtimeAPI(Api2)。我正在尝试使用Azure广告承载令牌进行身份验证。Api1的客户端是一个JavaScript客户端,它使用ADAL.js从Azure获取令牌Signalr 信号器Azure令牌的Web Api不工作,signalr,asp.net-web-api2,owin,azure-active-directory,Signalr,Asp.net Web Api2,Owin,Azure Active Directory,我有一个Asp.NETWebAPI(Api1),需要将消息发送到SignalrRealtimeAPI(Api2)。我正在尝试使用Azure广告承载令牌进行身份验证。Api1的客户端是一个JavaScript客户端,它使用ADAL.js从Azure获取令牌 var authContext = new AuthenticationContext({ tenant: tenantId, clientId: jsclientId,
var authContext = new AuthenticationContext({
tenant: tenantId,
clientId: jsclientId,
postLogoutRedirectUri: window.location.origin,
cacheLocation: 'localStorage',
endpoints: {
api1Url: api1ResourceUri
}
});
authContext.acquireToken(jsclientId, function (error, token) {
if (error || !token) {
authContext.clearCache();
authContext.login();
}
});
JS客户端在授权头中将此令牌附加到对Api1的所有Api调用。在Api1中,我使用以下代码从Azure AD获取访问令牌
var userAssertion = new UserAssertion(bootstrapContext.Token, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);
var result = await authenticationContext.AcquireTokenAsync(api2ResourceId, new ClientCredential(api1clientId, api1clientSecret), userAssertion);
我将此访问令牌作为授权头“承载令牌值”附加到请求中。在Signalr Hub Owin启动类中,我有以下代码
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters
{
ValidAudiences = api1Audiences,
SaveSigninToken = true
},
Tenant = configSection.TenantId
});
虽然集线器上的ClaimSideEntity显示为已验证,但未设置用户的身份。identity.name为空。看起来用户身份没有传递到信号器集线器 API中没有用户标识,因为您是作为应用程序而不是用户对其进行身份验证 acquireTokenAsync重载仅接收资源和ClientCredentials,用于客户端凭据流(也称为仅应用程序流) 您需要做的是使用代表流将您为API1获得的令牌交换为API2的令牌 因此,在API1的Startup.Auth、TokenValidation参数中,将Save SigninToken设置为true,如下所示:
app.UseOpenIdConnectAuthentication(
OpenIdConnectAuthenticationOptions
{
// ...
TokenValidationParameters = new TokenValidationParameters
{
SaveSigninToken = true
},
// ...
});
然后,无论您想在哪里调用API2,请执行以下操作:
ClientCredential clientCred = new ClientCredential(clientId, appKey);
var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext;
string userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
string userAccessToken = bootstrapContext.Token;
UserAssertion userAssertion = new UserAssertion(bootstrapContext.Token, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);
result = await authContext.AcquireTokenAsync(api2ResourceId, clientCred, userAssertion);
请参见示例:,具体是ToDoService的Startup.Auth.cs和TodoListController.cs
注意:此示例适用于本机应用程序+web api,您正在将其改编为web应用程序+web api
编辑-通过在JS acquireToken调用中指定API1,确保JS代码正在为API1请求令牌,如下所示:
var authContext = new AuthenticationContext({
tenant: tenantId,
clientId: jsclientId,
postLogoutRedirectUri: window.location.origin,
cacheLocation: 'localStorage',
endpoints: {
api1Url: api1ResourceUri
}
});
authContext.acquireToken(api1clientId, function (error, token) {
if (error || !token) {
authContext.clearCache();
authContext.login();
}
});
我的错,应该是api2ResourceId,修复了它。我更新了AcquireTokenAsync和UserAssertion,如前所述。现在我得到一个错误“断言受众声明与所需值不匹配”。它说预期的受众是Api1的受众,但受众是调用Api1的javascript客户机的受众。我已经更新了问题以显示JS客户端代码。您在AcquireContext调用中仍然缺少UserAssertion。很抱歉,我没有完全更新问题。我正在AcqureToken调用中传递userAssertion。听起来您有3个Azure AD应用程序。一个用于JS客户端,一个用于API 1,一个用于API 2。您能否更新您的问题,以便所有资源和客户端标识它们属于哪个应用程序?i、 e.客户顾问、资源顾问等。。。