130 lines
3.5 KiB
JavaScript
130 lines
3.5 KiB
JavaScript
import { URL } from 'node:url';
|
|
import { MultiSamlStrategy } from '@node-saml/passport-saml';
|
|
import passport from 'passport';
|
|
|
|
import appConfig from '../config/app.js';
|
|
import createAuthTokenByUserId from './create-auth-token-by-user-id.js';
|
|
import SamlAuthProvider from '../models/saml-auth-provider.ee.js';
|
|
import AccessToken from '../models/access-token.js';
|
|
import findOrCreateUserBySamlIdentity from './find-or-create-user-by-saml-identity.ee.js';
|
|
|
|
const asyncNoop = async () => { };
|
|
|
|
export default function configurePassport(app) {
|
|
app.use(
|
|
passport.initialize({
|
|
userProperty: 'currentUser',
|
|
})
|
|
);
|
|
|
|
passport.use(
|
|
new MultiSamlStrategy(
|
|
{
|
|
passReqToCallback: true,
|
|
getSamlOptions: async function (request, done) {
|
|
// This is a workaround to avoid session logout which passport-saml enforces
|
|
request.logout = asyncNoop;
|
|
request.logOut = asyncNoop;
|
|
|
|
const { issuer } = request.params;
|
|
const notFoundIssuer = new Error('Issuer cannot be found!');
|
|
|
|
if (!issuer) return done(notFoundIssuer);
|
|
|
|
const authProvider = await SamlAuthProvider.query().findOne({
|
|
issuer: request.params.issuer,
|
|
});
|
|
|
|
if (!authProvider) {
|
|
return done(notFoundIssuer);
|
|
}
|
|
|
|
return done(null, authProvider.config);
|
|
},
|
|
},
|
|
async function signonVerify(request, user, done) {
|
|
const { issuer } = request.params;
|
|
const notFoundIssuer = new Error('Issuer cannot be found!');
|
|
|
|
if (!issuer) return done(notFoundIssuer);
|
|
|
|
const authProvider = await SamlAuthProvider.query().findOne({
|
|
issuer: request.params.issuer,
|
|
});
|
|
|
|
if (!authProvider) {
|
|
return done(notFoundIssuer);
|
|
}
|
|
|
|
const foundUserWithIdentity = await findOrCreateUserBySamlIdentity(
|
|
user,
|
|
authProvider
|
|
);
|
|
|
|
request.samlSessionId = user.sessionIndex;
|
|
|
|
return done(null, foundUserWithIdentity);
|
|
},
|
|
async function logoutVerify(request, user, done) {
|
|
const { issuer } = request.params;
|
|
const notFoundIssuer = new Error('Issuer cannot be found!');
|
|
|
|
if (!issuer) return done(notFoundIssuer);
|
|
|
|
const authProvider = await SamlAuthProvider.query().findOne({
|
|
issuer: request.params.issuer,
|
|
});
|
|
|
|
if (!authProvider) {
|
|
return done(notFoundIssuer);
|
|
}
|
|
|
|
const foundUserWithIdentity = await findOrCreateUserBySamlIdentity(
|
|
user,
|
|
authProvider
|
|
);
|
|
|
|
const accessToken = await AccessToken.query().findOne({
|
|
revoked_at: null,
|
|
saml_session_id: user.sessionIndex,
|
|
}).throwIfNotFound();
|
|
|
|
await accessToken.revoke();
|
|
|
|
return done(null, foundUserWithIdentity);
|
|
}
|
|
)
|
|
);
|
|
|
|
app.get(
|
|
'/login/saml/:issuer',
|
|
passport.authenticate('saml', {
|
|
session: false,
|
|
successRedirect: '/',
|
|
})
|
|
);
|
|
|
|
app.post(
|
|
'/login/saml/:issuer/callback',
|
|
passport.authenticate('saml', {
|
|
session: false,
|
|
}),
|
|
async (request, response) => {
|
|
const token = await createAuthTokenByUserId(request.currentUser.id, request.samlSessionId);
|
|
|
|
const redirectUrl = new URL(
|
|
`/login/callback?token=${token}`,
|
|
appConfig.webAppUrl
|
|
).toString();
|
|
response.redirect(redirectUrl);
|
|
}
|
|
);
|
|
|
|
app.post(
|
|
'/logout/saml/:issuer',
|
|
passport.authenticate('saml', {
|
|
session: false,
|
|
}),
|
|
);
|
|
}
|