passport-steam: InternalOpenIDError: Failed to verify assertion

Hello,

I’ve been running in this issue all day, and I still don’t know totally how to fix it.

I’ve got this error with this module, both on node 4.4 and node 6.0

InternalOpenIDError: Failed to verify assertion
    at D:\Projects\csgo\node_modules\passport-steam\node_modules\passport-openid-node6support\lib\passport-openid\strate
gy.js:184:36
    at Object.openid.verifyAssertion (D:\Projects\csgo\node_modules\passport-steam\node_modules\passport-openid-node6sup
port\node_modules\openid\openid.js:916:14)
    at openid.RelyingParty.verifyAssertion (D:\Projects\csgo\node_modules\passport-steam\node_modules\passport-openid-no
de6support\node_modules\openid\openid.js:65:10)

So naturally I digged in the source code, and changed this line:

  , OpenIDStrategy = require('passport-openid-node6support').Strategy

to:

  , OpenIDStrategy = require('passport-openid').Strategy

This resolved the issue on node 4.4, but got an error on node 6.0 (that’s why that modules is created i guess):

error: An uncaught exception has taken place! TypeError: params.hasOwnProperty is not a function
    at _checkSignatureUsingProvider (D:\Projects\csgo\node_modules\passport-openid\node_modules\openid\openid.js:1148:15
)
    at _checkSignature (D:\Projects\csgo\node_modules\passport-openid\node_modules\openid\openid.js:1083:5)
    at _verifyAssertionAgainstProviders (D:\Projects\csgo\node_modules\passport-openid\node_modules\openid\openid.js:104
7:12)

Anyone has fixed that first issue? There where some discussions with the same issue, but nothing fixed that for me (relevant: #27 ). These are part of my code:

passport.use(new SteamStrategy({
        returnURL: 'http://**snap**/api/auth/return',
        realm: 'http://**snap**',
        apiKey: config.get('apiKey'),
        stateless: true
    },
    function(identifier, profile, done) {
        console.log(identifier); //Logging output
        console.log(profile);
        profile.identifier = identifier;
        return done(null, profile);
    }
));
router.route('/')
    .get(passport.authenticate('steam'));

router.route('/return')
    .get(passport.authenticate('steam', { failureRedirect: '/' }),
        function (req, res) {
            console.log(req.user);
            res.redirect('/');
        }
    );

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 6
  • Comments: 60 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Before I start with the explanation of this issue, here the main facts:

  • This is not an issue of passport-steam
  • This is not an issue of node-openid
  • This is not an issue of passport-openid
  • This issue only appears when an express.js router is used

Let us start with the following setup:

app.js:

var authRoutes = require('./routes/auth.js');
app.use('/auth', authRoutes );

/routes/auth.js:

var express = require('express');
var router = express.Router();

router.get('/steam',
   passport.authenticate('steam', { failureRedirect: '/' }),
   function(req, res) {
      res.redirect('/');
   });

router.get('/steam/response',
   passport.authenticate('steam', { failureRedirect: '/' }),
   function(req, res) {
      res.redirect('/');
   });

module.exports = router;

SteamStrategy configuration:

new SteamStrategy({
    returnURL: 'http://localhost:3000/auth/steam/response',
    realm: 'http://localhost:3000/',
    apiKey: 'Your API key here'
}

Now try to authenticate and you will receive the error “Failed to verify assertion”.

The error-message “Failed to verify assertion” is just a header for a more specific error. To find out what kind of error is returned, we need to inspect the attached openidError object.

Simply pass a callback to the passport.authenticate method:

router.get('/steam/response',
   passport.authenticate('steam', function(err){
      console.log(err); // Returns the openidError object
   });

The route above will not continue since we didn’t specify any res.send nor next(). This not important cus we only want to receive the error object in our console.

Once ran, the following error was returned:

openidError: { message: ‘Invalid return URL’ } }

As you can see, the return URL appeard to be invalid. So I checked the return URL with my SteamStrategy configuration, but nothing seemed wrong.

node-openid/openid.js Going deeper by following the error-stack, I found out that in the node-openid module, the pathname of the assertionUrl did not match the received pathname.

if (originalReturnUrl.protocol !== receivedReturnUrl.protocol || // Verify scheme against original return URL
      originalReturnUrl.host !== receivedReturnUrl.host || // Verify authority against original return URL
      assertionUrl.pathname !== receivedReturnUrl.pathname) { // Verify path against current request URL
        console.log(assertionUrl.pathname); //<-- Wrong URL
        console.log(receivedReturnUrl.pathname); //<-- Correct URL
    return false;
  }

=> https://github.com/havard/node-openid/blob/master/openid.js#L938

I noticed that the assertionUrl.pathname did not return the same URL as set up in the SteamStrategy configuration.

Output: 8tbagas

So I went upwards the stack to check what URL is used during the assertion-verification-procedure.

passport-openid/strategy.js:

this._relyingParty.verifyAssertion(req.url, function(err, result) {

=> https://github.com/jaredhanson/passport-openid/blob/master/lib/passport-openid/strategy.js#L183

Interesting!

As you can see the module passport-openid uses req.url in order to verify the assertion. While this is perfectly fine, it conflicts with an express.Router:

See the statement in the Express API documentation:

[…] the “mounting” feature of app.use() will rewrite req.url to strip the mount point.

=> http://expressjs.com/de/api.html#req.originalUrl

Bingo!

That is why req.url will not return the full-path, eg. the mount point.

In order to keep the mount point we must use req.originalUrl instead of req.url

You can test this with a simple setup:

app.js:

var authRoutes = require('./routes/auth.js');
app.use('/auth', authRoutes );

/routes/auth.js:

var express = require('express');
var router = express.Router();

router.get('/test', function(req, res, next) {
    console.log(req.url)
    console.log(req.originalUrl)
    next();
});

/* Output:
/test
/auth/test
*/

router.get('/test/response', function(req, res, next) {
    console.log(req.url)
    console.log(req.originalUrl)
    next();
});

/* Output:
/test/response
/auth/test/response
*/

Conclusion:

Use req.originalUrl instead of req.url.

Let’s do this by adding a simple middleware in front of passport.authenticate:

function use_orginalurl(req, res, next){
    req.url = req.originalUrl;
    next();
}

router.get('/steam/response', use_orginalurl, 
passport.authenticate('steam', { failureRedirect: '/' }),
function(req, res){
    res.redirect('/');
});

//or simpler:

router.get('/steam/response', 
   function(req, res, next){
      req.url = req.originalUrl; next();
   }, passport.authenticate('steam', { failureRedirect: '/' }),
   function(req, res){
      res.redirect('/');
   });

Just update all npm packages… it fixes the problem, the cause of problem is not about this repo… its about packages.

I got an alert for this so I guess I’ll post what it ended up being for me. My VPS provider switched me to a new box an in the process it killed my time. The ntp configuration was broken because they block most ip’s and for some reason my ntp server config was lost. I spent a good few days trying to figure out the problem and it ended up being the wrong time on my VPS.

Hope this help someone

List of errors returning “Failed to verify assertion”: https://i.imgur.com/TGiBv2C.png

Take a look to the five minutes limit and set the correct time on the server

@Burnett01 Thanks so much for your help! I’ve taken @beuted’s suggestion and created a separate example that demonstrates the workaround you’ve listed.

I’ve added you to the contributors list for your debugging work! Thanks!

@Burnett01 thanks a lot I had the exact same issue, nice workaround. This should be added to the example ! https://github.com/liamcurry/passport-steam/blob/master/examples/signon/app.js

@Burnett01 Beautifully explained. I haven’t been having this issue, but that should certainly clear everything up for those who are having the issue.

Provably it’s not your case but if the error is invalid or replied nonce check your system clock. In my case it was +2 hours and it wouldn’t work

I was able to fix this for myself. I used express-generator for my project. I have a file named auth.js in the /routes directory that handles the authentication. I export the router variable just like @mprey does. And in the main app.js file I have this:

var auth = require('./routes/auth');
app.use('/auth', auth);

So basically /auth/steam becomes /auth/auth/steam on the site. When I was doing it like this, I was experiencing the Failed to verify assertion error. Now, I’m using the auth variable on the website root, like so:

var auth = require('./routes/auth');
app.use('/', auth);

Now everything works fine. And all of the working examples I’ve seen have it on / Might be a bug. I’m fairly new to node, please correct me if there is any mistake in my analogy.