2

I am unable to retrieve the RelayState value. Can someone please direct me or provide a link to relevant documentation.

This is what I have so far as my setup and routes.

Setup

const saml_strategy = new saml.Strategy(
    {
        'callbackUrl': 'https://callback-url/adfs/postResponse',
        'entryPoint': 'https://entry-url/adfs/ls/',
        'issuer': 'issuer-name',
        'decryptionPvk': fs.readFileSync('./private.key', 'utf-8'),
        'cert': [idp_cert],
        'identifierFormat': null,
   'disableRequestedAuthnContext': true,
   'authnContext': ["urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"],
   'additionalParams':{'RelayState':'test'}
    }, 

Routes

app.get(
    '/', 
    function (req, res) {
        if (req.isAuthenticated()) 
        {
           res.send( '{ "authenticated": true }' );
        } 
        else 
        {
            res.send( '{ "authenticated":  false }' );
        }
    }
);

app.get(
    '/login', 
    passport.authenticate('saml', { 'successRedirect': '/', 'failureRedirect': '/login' }),
    function(req, res) 
      {
        res.redirect('/');
      }
);

///login/callback
app.post(
    '/adfs/postResponse',
    passport.authenticate('saml', { 'failureRedirect': '/', 'failureFlash': true }),
    function(req, res) 
    {
        res.redirect('/');
    }
);

1 Answer 1

4

RelayState is set from the query string of the initial login request page, and then (provided the IdP respects it), it is available in the body of the callback POST response.

So in your case, this should work:

app.get(
    '/login', 
    function(req, res, next){
        // you could redirect to /login?RelayState=whatever, or set query here,
        // the value must be encoded for passing in the query string:
        req.query.RelayState = encodeURIComponent('my relay state');
    },
    passport.authenticate('saml', { 'successRedirect': '/', 'failureRedirect': '/login' }),
    function(req, res) 
    {
        res.redirect('/');
    }
);
app.post(
    '/adfs/postResponse',
    passport.authenticate('saml', { 'failureRedirect': '/', 'failureFlash': true }),
    function(req, res) 
    {
        console.log(`relay state was ${decodeURIComponent(req.body.RelayState)}`);
        res.redirect('/');
    }
);
3
  • Thank you James, I will give it a try and let you know of the outcome.
    – lexma
    Commented Feb 9, 2021 at 14:21
  • Worked for me (Azure). Thank you!
    – Curious
    Commented Jul 5 at 16:20
  • This is a life saver, thank you! Worked for me in an Express/NestJS app with an internal company IdP server
    – Chris Barr
    Commented Aug 5 at 21:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.