API 不会使用从 SPA 使用 MSAL 传递的令牌针对 AAD 进行身份验证
API won't authenticate against AAD with token passed from SPA using MSAL
我正在尝试调整引用的示例 B2C 代码 here and here 以对抗我们组织的 AAD。
我有一个 SPA 应用程序,它通过 MSAL 成功地使用 AAD 进行身份验证并接收到令牌。 SPA 应用程序可以使用令牌从 MS Graph API 中提取数据——所以我确定令牌是有效的。
SPA 目前在 运行 本地 @ localhost:9000。
我有第二个应用程序,它是 Nodejs API 运行 @ localhost:3000。 SPA 应用程序调用 API,传递用于 GraphAPI 的相同令牌。 API 应用程序应该使用该令牌对用户进行身份验证并提供对 API 的访问;但是,我只得到 401 - 未经授权。
(我在客户端代码中使用 Aurelia。HTTP 请求是使用 Aurelia 的 HTTP 客户端发出的)。
这是用于调用 API 的 SPA 代码:
//Not entirely sure what to use as the scope here!! API is registered to allow user.read Graph API scope.
this.config.msClient.acquireTokenSilent(["user.read"]).then(token => {
console.log("Token acquired silently.");
this.makeAPICall(token);
}, error => { ... }
);
makeAPICall(token) {
this.http.configure(config => {
config
.withBaseUrl('http://localhost:3000/')
.withDefaults({
headers: {
'Authorization': 'Bearer ' + token
}
}
this.http.fetch("user/0")
.then(response => {
debugger; //response is 401 Unauthenticated at this point
}, error => { ... });
}
我已经在 apps.dev.microsoft.com 为我的 API 注册了一个应用程序。这是我的服务器端 (API) Nodejs 代码:
const express = require("express")
const port = 3000
const passport = require("passport")
var BearerStrategy = require("passport-azure-ad").BearerStrategy;
var userList = [
{id: 1, first: "Mickey", last: "Mouse", age: 95},
{id: 2, first: "Donald", last: "Duck", age: 85},
{id: 3, first: "Pluto", last: "leDog", age: 70}
]
var options = {
identityMetadata: "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration",
clientID: "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", //My registered App Id
passReqToCallback: false,
validateIssuer: true,
issuer: "xxxxxxx" //Our tenant name
};
var strategy = new BearerStrategy(options, (token, done) => {
console.log(token);
done(null,{}, {scope: '*'});
})
const app = express()
app.use(passport.initialize())
passport.use(strategy);
//Allow CORS
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin","*");
res.header("Access-Control-Allow-Headers","Authorization, Origin, X-Requested-With, Content-Type,Accept");
next();
})
app.get("/",(request, response) => { //Unauthenticated -- always works
response.send("Hello World!")
})
app.get("/user/:id",passport.authenticate('oauth-bearer',{session: false }),
(request, response) => {
//Never seem to get here (when debugging) as authenticate always fails
let id = request.params["id"];
let user = userList[id];
if(user) response.json(user);
else response.send("No user found")
})
app.listen(port, () => {
console.log("Listening on port " + port)
})
我确定我只是误解了这一切是如何工作的,但希望得到一些指导,了解我需要更改哪些内容才能使其正常工作。
令牌就像银行支票:它们只能由为其开具的人缓存。为 MS Graph 颁发的令牌将以 Microsoft Graph 为受众,并且应该仅由 Microsoft Graph 接受。收到该令牌的任何其他 API X 都应拒绝它。打算调用 X 的客户端应该为 X 请求一个令牌,无论它是否已经有另一个服务的令牌(如 Microsoft 图表)。这里有一个使用 ADAL JS 实现的流程示例:https://azure.microsoft.com/en-us/resources/samples/active-directory-angularjs-singlepageapp-dotnet-webapi/
此时 Azure AD v2(由 MSAL 使用)无法为自定义 API 颁发访问令牌:该功能正在开发中,但我们尚无预计何时可用于生产。在此之前,v2(因此是 MSAL JS)不支持此拓扑。抱歉!
一年后,现在可以使用 MSAL 保护您的自定义 API。在应用程序门户 (https://apps.dev.microsoft.com) 中,您可以创建您的应用程序,然后 "add a platform" 两次 - 一次用于您的网络应用程序 SPA,另一次用于您的网络 api。在网络 api 中,创建一个 "scope" 例如"api://e892d79e-03e7-4e5e-.../access_as_user",然后将此范围传递给 acquireTokenSilent 调用(而不是上面示例中的 "user.read")。
我正在尝试调整引用的示例 B2C 代码 here and here 以对抗我们组织的 AAD。
我有一个 SPA 应用程序,它通过 MSAL 成功地使用 AAD 进行身份验证并接收到令牌。 SPA 应用程序可以使用令牌从 MS Graph API 中提取数据——所以我确定令牌是有效的。
SPA 目前在 运行 本地 @ localhost:9000。
我有第二个应用程序,它是 Nodejs API 运行 @ localhost:3000。 SPA 应用程序调用 API,传递用于 GraphAPI 的相同令牌。 API 应用程序应该使用该令牌对用户进行身份验证并提供对 API 的访问;但是,我只得到 401 - 未经授权。
(我在客户端代码中使用 Aurelia。HTTP 请求是使用 Aurelia 的 HTTP 客户端发出的)。
这是用于调用 API 的 SPA 代码:
//Not entirely sure what to use as the scope here!! API is registered to allow user.read Graph API scope.
this.config.msClient.acquireTokenSilent(["user.read"]).then(token => {
console.log("Token acquired silently.");
this.makeAPICall(token);
}, error => { ... }
);
makeAPICall(token) {
this.http.configure(config => {
config
.withBaseUrl('http://localhost:3000/')
.withDefaults({
headers: {
'Authorization': 'Bearer ' + token
}
}
this.http.fetch("user/0")
.then(response => {
debugger; //response is 401 Unauthenticated at this point
}, error => { ... });
}
我已经在 apps.dev.microsoft.com 为我的 API 注册了一个应用程序。这是我的服务器端 (API) Nodejs 代码:
const express = require("express")
const port = 3000
const passport = require("passport")
var BearerStrategy = require("passport-azure-ad").BearerStrategy;
var userList = [
{id: 1, first: "Mickey", last: "Mouse", age: 95},
{id: 2, first: "Donald", last: "Duck", age: 85},
{id: 3, first: "Pluto", last: "leDog", age: 70}
]
var options = {
identityMetadata: "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration",
clientID: "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", //My registered App Id
passReqToCallback: false,
validateIssuer: true,
issuer: "xxxxxxx" //Our tenant name
};
var strategy = new BearerStrategy(options, (token, done) => {
console.log(token);
done(null,{}, {scope: '*'});
})
const app = express()
app.use(passport.initialize())
passport.use(strategy);
//Allow CORS
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin","*");
res.header("Access-Control-Allow-Headers","Authorization, Origin, X-Requested-With, Content-Type,Accept");
next();
})
app.get("/",(request, response) => { //Unauthenticated -- always works
response.send("Hello World!")
})
app.get("/user/:id",passport.authenticate('oauth-bearer',{session: false }),
(request, response) => {
//Never seem to get here (when debugging) as authenticate always fails
let id = request.params["id"];
let user = userList[id];
if(user) response.json(user);
else response.send("No user found")
})
app.listen(port, () => {
console.log("Listening on port " + port)
})
我确定我只是误解了这一切是如何工作的,但希望得到一些指导,了解我需要更改哪些内容才能使其正常工作。
令牌就像银行支票:它们只能由为其开具的人缓存。为 MS Graph 颁发的令牌将以 Microsoft Graph 为受众,并且应该仅由 Microsoft Graph 接受。收到该令牌的任何其他 API X 都应拒绝它。打算调用 X 的客户端应该为 X 请求一个令牌,无论它是否已经有另一个服务的令牌(如 Microsoft 图表)。这里有一个使用 ADAL JS 实现的流程示例:https://azure.microsoft.com/en-us/resources/samples/active-directory-angularjs-singlepageapp-dotnet-webapi/ 此时 Azure AD v2(由 MSAL 使用)无法为自定义 API 颁发访问令牌:该功能正在开发中,但我们尚无预计何时可用于生产。在此之前,v2(因此是 MSAL JS)不支持此拓扑。抱歉!
一年后,现在可以使用 MSAL 保护您的自定义 API。在应用程序门户 (https://apps.dev.microsoft.com) 中,您可以创建您的应用程序,然后 "add a platform" 两次 - 一次用于您的网络应用程序 SPA,另一次用于您的网络 api。在网络 api 中,创建一个 "scope" 例如"api://e892d79e-03e7-4e5e-.../access_as_user",然后将此范围传递给 acquireTokenSilent 调用(而不是上面示例中的 "user.read")。