parse nodejs node node.js express passport.js saml-2.0

node.js - nodejs - url parse js



¿Cómo redirecciono a la url solicitada originalmente después de la autenticación con passport-saml? (2)

¿Puedo enviar un url, o algún otro valor, al IdP que se redondeará y se enviará de nuevo en la respuesta SAML? Y si es así, ¿cómo puedo acceder a él en mi ruta / login / callback?

Para redondear un valor a través del IdP debe usar RelayState . Este es un valor que puede enviar al IdP y, si lo hace, están obligados a devolverlo sin modificaciones.

Aquí está lo que dicen las especificaciones de SAML :

3.1.1 Uso de RelayState

Algunos enlaces definen un mecanismo "RelayState" para preservar y transmitir información de estado. Cuando se utiliza un mecanismo de este tipo para transmitir un mensaje de solicitud como paso inicial de un protocolo SAML, establece requisitos sobre la selección y el uso de la vinculación utilizada posteriormente para transmitir la respuesta. A saber, si un mensaje de solicitud SAML está acompañado por datos de RelayState, entonces el respondedor de SAML DEBE devolver su respuesta de protocolo SAML utilizando un enlace que también admite un mecanismo de RelayState, y DEBE colocar los datos exactos de RelayState que recibió con la solicitud en el Estado de Relay correspondiente. Parámetro en la respuesta.

Para usar esto con passport-saml, debe agregarlo como un valor de Parámetros additionalParams . El siguiente código muestra que esto está sucediendo.

saml = new SamlStrategy path: appConfig.passport.saml.path decryptionPvk: fs.readFileSync(appConfig.passport.saml.privateKeyFile) issuer: appConfig.passport.saml.issuer identifierFormat: tenant.strategy.identifierFormat entryPoint: tenant.strategy.entryPoint additionalParams:{''RelayState'':tenant.key} , (profile, next) -> # get the user from the profile

El código de arriba es de una implementación saml de varios inquilinos, por lo que estoy enviando mi tenant.key como RelayState . Luego recupero este valor del cuerpo del retorno POSTADO del IdP y lo uso para restablecer todo el estado que necesito.

getTenantKey: (req, next) -> key = req.body?.RelayState ? routes.match(req.path).params.tenentKey next null, key

Su caso podría ser más simple. Probablemente querrá almacenar la url de destino final en un caché de tiempo limitado y luego enviar la clave de caché como el RelayState .

Por lo que vale la pena, puedes evitar usar RelayState completo si solo utilizas el ID de solicitud SAML original como tu clave de caché. Este valor siempre se le envía de vuelta a través del campo InResponseTo .

Disculpe si esta es una pregunta estúpida, pero tengo algunos problemas para entender cómo podría redireccionar el navegador del cliente a la URL que se solicitó originalmente después de una autenticación exitosa con nuestro proveedor de identidad SAML (IdP). Estoy usando las últimas versiones de pasaporte-saml, pasaporte y Express.

Por ejemplo, digamos que el cliente solicitó originalmente /foo/bar desde un enlace en otra página no protegida, pero dado que es un recurso protegido, respondo con un redireccionamiento a /login , que es donde llamo passport.authenticate(''saml'') .

app.get(''/login'', passport.authenticate(''saml'')); function ensureAuth(req, res, next) { if (req.user.isAuthenticated()) {return next();} else {res.redirect(''/login'');} } app.get(''/foo/bar'', ensureAuth, function(req, res) { ... });

Esa llamada redirigirá el navegador a la página de inicio de sesión de mi IdP y, luego de una autenticación exitosa, los IdP se enviarán a mi ruta /login/callback . En esa ruta, de nuevo uso passport.authenticate(saml) para validar la respuesta SAML, y si todo está bien, luego redirecciono el navegador al recurso solicitado ... pero, ¿cómo puedo saber cuál fue el recurso solicitado? ? Debido a que es una devolución de llamada POST, perdí cualquier estado asociado con la solicitud original.

app.post(''/login/callback'', passport.authenticate(''saml''), function(req, res) { res.redirect(''...can I know which url to redirect back to?...''); });

El ejemplo en el archivo readme de passport-saml solo muestra una redirección codificada de nuevo al recurso raíz, pero me gustaría redirigir nuevamente a la URL solicitada originalmente ( /foo/bar ).

¿Puedo enviar un url, o algún otro valor, al IdP que se redondeará y se enviará de nuevo en la respuesta SAML? Y si es así, ¿cómo puedo acceder a él en mi ruta /login/callback ?

¿O hay alguna forma mejor, expresa / pasaporte para hacer esto que me estoy perdiendo?

Cualquier ayuda que pueda proporcionar sería muy apreciada!


Si desea especificar RelayState por solicitud, podría pensar que podría hacer lo siguiente:

passport.authenticate(''saml'', { additionalParams: { RelayState: "foo" } })

Pero eso no funciona. Si nos fijamos en la implementación: https://github.com/bergie/passport-saml/blob/6d1215bf96e9e352c25e92d282cba513ed8e876c/lib/passport-saml/saml.js#L326 verás que los Paquetes adicionales se captan de la configuración inicial de la imagen. O desde el objeto req (pero no desde las opciones por solicitud).

Pero, afortunadamente, la estrategia SAML de Passport hace esto por solicitud:

var RelayState = req.query && req.query.RelayState || req.body && req.body.RelayState;

Luego, busca en las opciones de configuración más Paquetes adicionales (globales).

Por lo tanto, si desea especificar RelayParams en base a cada solicitud, debe cargarlos en la req antes de llamar a la autorización. En mi caso, hago algo como esto dentro del controlador de ruta:

req.query.RelayState = req.params.redirect_to; passport.authenticate(''saml'')(req, res, next);

Luego, cuando la solicitud redirigida regrese del IdP de SAML, debería poder utilizar req.body.RelayParams para acceder a su estado por solicitud.

Tenga en cuenta que si su valor de RelayParams es un objeto, es posible que tenga que usar JSON.stringify para codificarlo en RelayParams, y JSON.parse para descodificarlo (tuve que hacerlo en mi caso).