Пытаюсь вкрутить SSO в свой проект. Имеется федерация, которая предоставляет мне список IdP, через которые я могу аутентифицироваться. Использую для аутентификации
passport-saml.
export const samlFederationAuthentication = () => {
const multiSamlStrategy: MultiSamlStrategy = new MultiSamlStrategy(
{
passReqToCallback: true,
getSamlOptions: async (req: Express.Request, done: SamlOptionsCallback) => {
const entityID: string = decodeURIComponent((req.query.entityID as string) || '');
if (!entityID) {
return done(
CustomError(
'Not supported',
'SAML AUTH',
`EntityID is undefined`
)
);
}
const config = await samlFederation.getConfig(); // getting entrypoint and certificate
if (!config[entityID]) {
return done(
CustomError(
'Not supported',
'SAML AUTH',
`EntityID is not supported by IDp`
)
);
}
return done(null, {
...config[entityID],
callbackUrl: envConfig.samlFederation.callbackURL,
issuer: envConfig.samlFederation.issuer,
});
},
},
async (req: Express.Request, profile, done) => {
try {
const profileUsername: string = samlFederation.getProfileUsername(profile || {});
if (!profileUsername) {
return done(
CustomError(
'Username and email are undefined',
'SAML AUTH',
`Username or email should be defined in SAML profile`
)
);
}
const dbUser = await userService.getUserByUsername(profileUsername);
if (!!dbUser) {
return done(null, dbUser);
}
const createdUser: IUser = await userService.createUser(profile || {});
return done(null, createdUser as Record<string, any>);
} catch (err) {
return done(err);
}
}
);
Passport.use('multi-saml', multiSamlStrategy);
};
далее покажу обработку запросов, связанных с аутенфикацией:
export const addSamlFederationRoutes = (app: Express.Application) => {
app.get('/auth/saml', Passport.authenticate('multi-saml'));
app.post(
'/auth/saml/callback',
Passport.authorize('multi-saml', { failureRedirect: '/', failureFlash: true }),
userHandler // some handler with user data
);
};
Проблема моя состоит в следующем.
1. Сначала пользователь переходит на форму аутентификации, предоставляемую федерацией, на которой он может выбрать некоторый IdP
2. Данная форма отправляет запрос на наш сервер с идентификатором IdP (параметр
entityID), чтобы наш сервер перенаправил пользователя на сервер IdP.
3. Наш сервер получает идентификатор entityId, находит в своей базе данных URL перехода и редиректит пользователя по этому URL.
4. Пользователь вводит свои данные и аутентифицируется внутри IdP. IdP отсылает инфу о пользователе по URL
GET /auth/saml/callback
Далее собственно мы сталкиваемся с проблемой. Функция
getSamlOptions вызывается даже после аутентификации на IdP. И если разобрать выше приведённый код, то понятно будет, что у нас имеется попытка обратиться к
entityID, который собственно IdP на наш сервер уже не отсылает, поэтому всегда я получаю ошибку о том, что
entityID is undefined
. Помогите советом, как обойти вызов
getSamlOptions после аутентификации на IdP или как мне достать entityID в коллбэке.