我使用 passport-azure-ad 来处理涉及许多不同身份验证协议的复杂登录服务中的 Azure SSO。
建立客户端凭据流非常有效,其中会话由后端管理。
msal-node 库最好实现一个隐式流,其中 SPA 获得对令牌的访问权,然后可以使用该令牌从身份提供者获取数据。
另一种解决方法是使用 passport-azure-ad 来处理登录,然后将其绑定到自定义 JWT 生成系统。
最终会看起来像这样:
const passport = require('passport');
const OIDCStrategy = require('passport-azure-ad').OIDCStrategy;
const Token = require('Token.js');
settings = {
azureDirectoryId: '',
azureClientId: '',
azureClientSecret: '',
callbackUrl: 'https://example.com/auth/callback',
}
passport.use(new OIDCStrategy(
{
identityMetadata: `https://login.microsoftonline.com/${settings.azureDirectoryId}/.well-known/openid-configuration`,
clientID: settings.azureClientId,
responseType: 'code id_token',
responseMode: 'form_post',
redirectUrl: settings.callbackUrl,
clientSecret: settings.azureClientSecret,
// ...additional settings if needed
},
(req, iss, sub, profile, accessToken, refreshToken, done) => {
process.nextTick(async () => {
profile.accessToken = accessToken;
profile.refreshToken = refreshToken;
profile.token = Token.generate(profile);
done(null, profile);
});
},
));
router.get('/auth/login', (req, res, next) => {
passport.authenticate('azuread-openidconnect', {
response: res,
resourceURL: null,
customState: Math.random().toString(36).substr(2, 10),
failureRedirect: '/failure',
})(req, res, next);
});
router.use('/auth/callback', (req, res, next) => {
passport.authenticate('azuread-openidconnect', {
response: res,
successRedirect: '/success',
failureRedirect: '/failure',
})(req, res, next);
});
router.get('/auth/success', (req, res, next) => {
if (req.user.token) {
res.cookie('token', req.user.token);
return res.redirect('https://example.com');
}
failure(req, res);
});
const failure = (req, res) => {
req.session.destroy(() => {
res.clearCookie('token', cookieSettings);
res.redirect('https://example.com');
});
};
router.get('/auth/failure', failure);
这样,将用户发送到https://example.com/auth/login 将开始通过护照进行身份验证的过程。完成后,您将使用身份提供者 (Token.generate(profile);) 返回的信息生成 JWT,将该令牌存储为 cookie,并将用户重定向回主页。