To solve this, I'm using the node.js package express-force-domain
Problems authenticating with Reddit OAuth in 'www' subdomain
-
29-08-2022 - |
سؤال
I currently have Reddit authorization set up for my Node app just like in this example. I have the app on Reddit setup for the callback url http://example.com/auth/reddit/callback
and everything is fine. Users can enter http://example.com/auth/reddit
and log in and everything is good.
The problem comes in when a user tries to log in through http://www.example.com/
. It appears that Reddit's CSRF protection sees these requests as an issue. As per the example:
/**
* Authentication route
*/
app.get('/auth/reddit', function(req, res, next) {
var n = crypto.randomBytes(32).toString('hex');
req.session.state = n;
passport.authenticate('reddit', {
state : n,
duration : 'permanent'
})(req, res, next);
});
/**
* Authentication callback
*/
app.get('/auth/reddit/callback', function(req, res, next) {
// Check for origin via state token
if (req.query.state === req.session.state) {
/* authenticate the user */
} else { next(new Error(403)); }
}
For requests from http://example.com/auth/reddit
, req.query.state === req.session.state
. However, for requests made from http://www.example.com/auth/reddit
, these values do not match. req.query.state
takes the new state value, but req.session.state
retains an old state value.
Is there a good work-around or solution to this problem? One work-around could be to automatically redirect all 'www' request to the root, but I haven't found a way to do that. Another option would be to remove the state check, but this would open up my code to CSRF attacks. Leaving everything as-is is not an option, as to users it's (understandably) very counter-intuitive to have the root domain work but the 'www' subdomain not work.
Thanks!
المحلول 2
نصائح أخرى
From what I understand, reddit redirects the user back to non-www domain, as per reddit application setup, and thus your session data is not available to you.
There are two solutions to this:
Configure cookies to use
.mydomain.com
. See this answer for details.Ignore state flag, since it's not mandatory in OAuth2 spec, albeit recommended. Example has it for one simple reason, reddit fails to process a request if state field is not present. At least is was the case when I was writing the library. You are free to send any random string as a state value without checking for it on return.
I'd personally recommend the first approach as a default one, since state flag is designed to prevents a certain type of attack. You might want to go with second approach for simplicity, but do so only if you're well informed of potential consequences - which might strip it of the simplicity value.