来自 SPA 应用程序的 AAD 令牌可以调用 Nodejs API 但不能调用 .Net WebAPI
AAD Token from SPA app works to call Nodejs API but not .Net WebAPI
我有一个 SPA 应用程序,它使用 MSAL 从 AAD 获取令牌。因为 MSAL 使用 v2 端点并且因为 v2 端点当前不支持为自定义 API 颁发令牌,所以我将 ID 令牌传递到我的 api 并且基本上将我的 api 视为同一个应用程序。 (虽然这有点味道,但它确实有效——至少对于 Nodejs API)。
SPA 应用程序
let idToken = Msal.Storage('localStorage').getItem(Msal.Constants.idTokenKey);
this.http.configure(config => {
config.withBaseUrl("http://localhost:3001/")
config.withDefaults({headers: {'Authorization': 'Bearer ' + idToken}})
});
//Call API
this.http.fetch("account")
...
Node.js API
//Using express/passport
var BearerStrategy = require("passport-azure-ad").BearerStrategy;
var options = {
identityMetadata: "https://login.microsoftonline.com/tenantid/.well-known/openid-configuration/",
clientID: "xxxxxxx-xxxx-xxxxxxx-xxxxx",
passReqtoCallback: false,
validateIssuer: true,
issuer: "http://login.microsoftonline.com/{tenantid}/v2.0"
};
app.get("/account",passport.authenticate('oauth-bearer',{session: false}),...
以上都有效。一旦用户通过 SPA 进行身份验证,令牌就会被传递并且对节点的调用 API 有效。
我现在正在尝试用 .Net WebAPI 替换 Nodejs API。我有以下内容:
Startup.cs
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters
{
//Same ID as used for ClientID in Nodejs
ValidAudience = "xxxxxx-xxxxx-xxxxx-xxxxx",
ValidIssuer = "https://login.microsoftonline.com/{tenantid}/v2.0",
ValidateIssuer = true,
AuthenticationType = "WebApi" //Tried both with and without this
},
Tenant = "{tenantid}" //have tried both id and name
}
)
AccountController.cs
[Authorize]
[Route("account")]
public IHttpActionResult AccountProfile(){
//Get Account information
....
return Ok(profile);
}
但是,当我将 SPA 应用程序指向调用 .Net api 时,我总是得到 Authorization has been denied for this request
。
有什么我遗漏的吗?
编辑
顺便说一句,我检查了正在使用的令牌。
我为 clientID
(Nodejs) 和 ValidAudience
(.Net) 使用的值与令牌中的 aud
声明完全匹配。 issuer
(Nodejs) 和 ValidIssuer
(.Net) 与令牌中的 iss
声明完全匹配。最后,在我插入 {tenantid} 的代码中的任何位置,那里的实际值与令牌中的 tid
声明完全匹配。
我们在从 ADAL 切换到 MSAL 时遇到了类似的问题,并通过使用类似 this Github project 的方法使其正常工作。具体看一下这些文件:
https://github.com/oktadeveloper/okta-oauth-aspnet-codeflow/blob/master/Api/Startup.cs
https://github.com/oktadeveloper/okta-oauth-aspnet-codeflow/blob/master/Api/OpenIdConnectCachingSecurityTokenProvider.cs
更新:我们的 Startup.cs:
var provider = new OpenIdConnectCachingSecurityTokenProvider(
string.Format(bc2Instace, tenant, policyId));
var jwt = new JwtFormat(clientId, provider);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
AccessTokenFormat = jwt,
});
我有一个 SPA 应用程序,它使用 MSAL 从 AAD 获取令牌。因为 MSAL 使用 v2 端点并且因为 v2 端点当前不支持为自定义 API 颁发令牌,所以我将 ID 令牌传递到我的 api 并且基本上将我的 api 视为同一个应用程序。 (虽然这有点味道,但它确实有效——至少对于 Nodejs API)。
SPA 应用程序
let idToken = Msal.Storage('localStorage').getItem(Msal.Constants.idTokenKey);
this.http.configure(config => {
config.withBaseUrl("http://localhost:3001/")
config.withDefaults({headers: {'Authorization': 'Bearer ' + idToken}})
});
//Call API
this.http.fetch("account")
...
Node.js API
//Using express/passport
var BearerStrategy = require("passport-azure-ad").BearerStrategy;
var options = {
identityMetadata: "https://login.microsoftonline.com/tenantid/.well-known/openid-configuration/",
clientID: "xxxxxxx-xxxx-xxxxxxx-xxxxx",
passReqtoCallback: false,
validateIssuer: true,
issuer: "http://login.microsoftonline.com/{tenantid}/v2.0"
};
app.get("/account",passport.authenticate('oauth-bearer',{session: false}),...
以上都有效。一旦用户通过 SPA 进行身份验证,令牌就会被传递并且对节点的调用 API 有效。
我现在正在尝试用 .Net WebAPI 替换 Nodejs API。我有以下内容:
Startup.cs
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters
{
//Same ID as used for ClientID in Nodejs
ValidAudience = "xxxxxx-xxxxx-xxxxx-xxxxx",
ValidIssuer = "https://login.microsoftonline.com/{tenantid}/v2.0",
ValidateIssuer = true,
AuthenticationType = "WebApi" //Tried both with and without this
},
Tenant = "{tenantid}" //have tried both id and name
}
)
AccountController.cs
[Authorize]
[Route("account")]
public IHttpActionResult AccountProfile(){
//Get Account information
....
return Ok(profile);
}
但是,当我将 SPA 应用程序指向调用 .Net api 时,我总是得到 Authorization has been denied for this request
。
有什么我遗漏的吗?
编辑
顺便说一句,我检查了正在使用的令牌。
我为 clientID
(Nodejs) 和 ValidAudience
(.Net) 使用的值与令牌中的 aud
声明完全匹配。 issuer
(Nodejs) 和 ValidIssuer
(.Net) 与令牌中的 iss
声明完全匹配。最后,在我插入 {tenantid} 的代码中的任何位置,那里的实际值与令牌中的 tid
声明完全匹配。
我们在从 ADAL 切换到 MSAL 时遇到了类似的问题,并通过使用类似 this Github project 的方法使其正常工作。具体看一下这些文件:
https://github.com/oktadeveloper/okta-oauth-aspnet-codeflow/blob/master/Api/Startup.cs https://github.com/oktadeveloper/okta-oauth-aspnet-codeflow/blob/master/Api/OpenIdConnectCachingSecurityTokenProvider.cs
更新:我们的 Startup.cs:
var provider = new OpenIdConnectCachingSecurityTokenProvider(
string.Format(bc2Instace, tenant, policyId));
var jwt = new JwtFormat(clientId, provider);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
AccessTokenFormat = jwt,
});