Multiple regions for passport-bnet in Node

API Discussion
I noticed that using passport-bnet in Node only allows you to configure a single region at application start-up, which makes it difficult to allow users to sign on with their Battle.net ID from other regions.

Here is the solution I've come up with to resolve this. There are no changes to the callback in your settings and no changes to the code of either passport or passport-bnet.

First, you need to set up multiple BnetStrategies, each configured with a different region, and named appropriately (I used bnet-<region>). This is a legitimate thing to do, since you might equally have several strategies for different providers. Note that the callbackURL now has a region parameter, which is not included in the callback URL in your application settings. Battle.net does not seem to mind that parameters are appended to the callback URL as long as the URL up to the param is identical.

passport.use('bnet-eu', new BnetStrategy({
region: 'eu',
clientID: BNET_ID,
clientSecret: BNET_SECRET,
scope: 'wow.profile',
callbackURL: 'https://lvh.me:3043/auth/bnet/callback?region=eu'
}, function (accessToken, refreshToken, profile, done) {
profile.region = 'eu';
console.info(profile);

Next, you need to parameterise the call to /auth/bnet and /auth/callback with your region, which could be stored in the session, or in my example the request. This can be done by wrapping the passport.authenticate() function in another function supplying the request object, making query strings and sessions available to the authenticate() function:
router.get('/auth/bnet', function (req, res, next) {
passport.authenticate('bnet-' + req.query.region, function (err, user, info) {
if (err) {
return next(err)
}
if (!user) {
return res.redirect('/')
}
res.redirect('/');
})(req, res, next);
});
router.get('/auth/bnet/callback', function (req, res, next) {
passport.authenticate('bnet-' + req.query.region, {
failureRedirect: '/',
successRedirect: '/'
})(req, res, next);
});

Finally, make the Login button pass a region as a parameter to to the /auth/bnet route (here's my Jade):
form(action="/auth/bnet", method="get")
select(name="region", id="region")
option(value="eu") EU
option(value="us") US
button(type="submit") Log in with Battle.net


So, in summary, your HTML form calls the /auth/bnet route with your region as a query parameter. This tells passport to use the BnetStrategy you configured with an appropriate name. This will head of to Battle.net with the region appended to the callback URL, which when called will return your user, configured to the correct region.

Seems to work for me :)
Thanks for sharing, Billi! Hopefully this will prove useful to other devs working on sites that support multiple regions :D.

Join the Conversation

Return to Forum