express-stormpath login not working for email-authenticated users - javascript

i have a basic node.js / Express server using express-stormpath for user authentication. everything works beautifully without email verification. obviously, email verification is desirable for many reasons, but my email-verified users are unable to use the standard login flow for restricted routes.
specific example on a custom route i have:
app.get('/myaccount', stormpath.loginRequired, function(req,
res.send('Your email address is: ' + req.user.email);});
this route works perfectly for users that registered before email verification.
however, it's broken for users that signed up after email verification. these users received an email, clicked the link, got the confirmation screen ("You account was successfully verified and is ready for use"), and are marked as 'Enabled' in my Stormpath dashboard.
specifically, if they enter the correct password, they are sent to http://glacial-hollows-8156.herokuapp.com/login?next=%2Fmyaccount again, which presents the login screen once more, ad infinitum. if they enter an incorrect password, they get the standard error telling them so
any ideas? perhaps email-verified accounts are not being initialized correctly? the behavior is also the same for Stormpath-provided routes like '/me', so i don't think its my route. as i turn email verification on and off, /myaccount keeps working for non email-verified users, and always breaks in this manner for the email-verified users

this was a config issue with 'Link Base URL' on the stormpath dashboard
it had defaulted to 'https://api.stormpath.com/emailVerificationTokens', which verifies users - although they can't actually log in
instead, change 'Link Base URL' to http://localhost:3000/verify
note that this link is totally out of date, despite being only 3 months old... https://stormpath.com/blog/how-to-add-billing-to-your-api/ do not bother trying to use /verified

Related

Is it bad to return a server error if user submits content they are not authorized too?

So I have a app where users can sign in with Twitter, Google and local. (I'm using passportjs)
If the users are signed in with Twitter or google I don't want to display options such as change email password etc.
To solve this in handlebars I check if a Twitter Id or google Id exist, if they do I hide the buttons to change email & password and instead display a message saying they cant change the email.
Now the problem is that if the user knows the route to the password change page (which isn't hard to figure out) they can still access the change password page. If they try to "change" their password they get a 500 response.
Is this a bad way to handle this specific situation? Does this open up other risks I'm not aware of?
Note: this is an expressjs app with handlebars template engine and passportjs.
Thanks.
The best way to approach what you are looking for would be to implement some middleware to prevent unauthorized users to upload content in the first place.
You can then throw errors from the controller just in case your middleware has some sort of leak.
Try something like (pseudocode):
(req, res, next)=>{
if ("User is authenticated"){
next()
}
res.redirect("Login page")
}

Redirection not working on Safari and Firefox

I'm using express-ntlm for authenticate my users on my app. For Mac OS, browsers ask for username and password and when a user insert a wrong password, it shows a page with a forbidden message. I overwrite forbidden function on my custom library so I can redirect users to the current URL so they can insert username and password again. For some reason this works on Chrome but not on Firefox or Safari, it just keep refreshing the page but doesn't prompt users for username and password. Looks like browser is storing the failed tried of log in and doesn't let you try again.
forbidden: function(req,res){
res
.status(401)
.send(`<!DOCTYPE html><html><head><body>
<h2>Login failed, Please try again.</h2></body></head>
<script>
window.setTimeout(function() {
window.location.href = '${req.url}';
}, 1000);
</script></html>`)
}
NTLM only makes sense, if you use it for SSO (without manually entering credentials).
In your case I would suggest you to create your own username/password form and then use some Active Directory / LDAP module to authenticate against the Domain Controller. If it succeeds the user will be logged in, otherwise you show an error and the user can try again.
You can also combine them and use express-ntlm if a browser comes along that support NTLM (e.g. IE) and otherwise show a login form. In my opinion this would be the biggest benefit and best UX for your users.

Nodemailer, Heroku, Gmail, invalid login - works locally

I have been having this issue for the past couple of weeks, it works every time locally, however once I deploy it to my heroku server, it will give me an invalid login error. I have gone into the account and givin access to less secure apps. And the credentials are correct, and it works on localhost every time. Is there something I am missing?
quickSendMail: function(routeBody, callback) {
//configuring the nodemailer for email notifications
var smtpConfig = {
host: 'smtp.gmail.com',
port: 465,
secure: true, // use SSL
auth: {
user: 'mysmtpemail123',
pass: '******'
}
};
var mailOptions = {
from: 'SageStorm Site <mysmtpemail123#gmail.com>',
to: ['my email'],
subject: routeBody.subject,
html: 'my message'
};
var transporter = nodemailer.createTransport(smtpConfig);
transporter.verify(function(error, success) {
if (error) {
console.log(error);
} else {
console.log('server is ready to send emails');
}
})
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
return callback(err, null);
} else {
console.log('Message sent: ' + info.response);
return callback(null, info);
}
})
}
You can allow machines to access your gmail remotely using this link, but keep in mind that Google will affect your default account (even if you are connected with another one).
The easy way: use a incognito / private window (to have no google account connected) and log in your google account and then use the link above.
If that doesn't work try updating your nodemailer to the latest version.
According to https://support.google.com/accounts/answer/6009563, Go to https://accounts.google.com/b/0/DisplayUnlockCaptcha and allow access and try again ..
Also according to docs at nodemailer (https://github.com/nodemailer/nodemailer#delivering-bulk-mail)
I'm having issues with Gmail Gmail either works well or it does not
work at all. It is probably easier to switch to an alternative service
instead of fixing issues with Gmail. If Gmail does not work for you
then don't use it.
I set a bounty to this question, but after looking through the Nodemailer docs/Github, it seems that using Gmail will only lead to headaches.
According to the Nodemailer docs...
"...Gmail expects the user to be an actual user not a robot so it runs a lot of heuristics for every login attempt and blocks anything that looks suspicious to defend the user from account hijacking attempts.
For example you might run into trouble if your server is in another geographical location – everything works in your dev machine but messages are blocked in production."
I believe the second thing was my issue; my Nodemailer ran without issue on my machine, but immediately failed when I pushed the app to Heroku.
As for a fix, my only fix was to use a different email provider. All email accounts I've tried using have been fully authorized to allow other sign-ins and less safe apps; I've gone through every method Google has to offer to allow usage of the account, and I fully believe that it's simply not possible to get consistent results with Nodemailer and Gmail.
Using Outlook/Hotmail worked for me. I also tried switching to a different Gmail account. It worked successfully a couple times, then returned to the previous state.
Most times when one ends up with this kinda error from Nodemailer, one of these options listed by Google gets to fix it, take your time to go through the google account to be used has the required setting.
Google has listed all the potential problems and fixes for us. In as much as you turned on less secure apps setting. Be sure you are applying these to the correct account.
Step 1: Check your password
If you have these problems or can’t sign in, first check to make sure you’re using the right password.
Step 2: Try these troubleshooting steps
If you've turned on 2-Step Verification for your account, you might need to enter an App password instead of your regular password.
Sign in to your account from the web version of Gmail at https://mail.google.com. Once you’re signed in, try signing in to the mail app again.
Visit Display Unlock Captcha and sign in with your Gmail username and password. If asked, enter the letters in the distorted picture.
Your app might not support the latest security standards. Try changing a few settings to allow less secure apps access to your account.
Make sure your mail app isn't set to check for new email too often. If your mail app checks for new messages more than once every 10 minutes, the app’s access to your account could be blocked.

Is it possible to post to chat.postMessage as any user in a Slack team?

I'm building a Slack integration that is intended to modify some text and then post it to a Slack channel as though the user who triggered the command had said it.
e.g. /makeFace disapproval
#Ben 3:45pm
ಠ_ಠ
I ask for the client permission scope, which adds the chat:write:user permission. But when I hit the chat.postMessage endpoint, it only seems to allow you to post as the user who added the integration because the token it returns seems to be individuated for that user.
I know that giphy, for instance, sends its gif messages as though you are the originator, but I can't find out how they manage it. Is there any documentation for sending messages as other members of the team?
There are 2 ways to achieve this:
A. Overwriting username and icon
When you send a message with chat.postMessage it is possible to set a user name with the property username. The message will then appear as being send by that user (same for icon with icon_url).
However, this is not meant to impersonate real users, so even if you use the same username and icon as the real user the message will have the app tag, so that they can be distinguished from a real user.
Here is an example how it looks like (from a gamer Slack about flying and killing space ships):
But depending on what your requirements are that might work for you.
If you want to use it make sure to also set the as_user property to false (yes, really) and it will not work with a bot token, only with a user token.
See here for more details on how it works.
This also works for the legacy version of Incoming Webhooks, not with the current version of incoming webhooks though. (You can still get the legacy version, see this answer)
B. Having the user's token
Another approach is to always use the token from the respective user for sending the message. In combination with as_user = true messages sent by your app will look exactly as if they would come from the respective user (no APP tag).
To make that happen your app would need to collect tokens from all users on your workspace and store them for later use. This can be done by asking every user to install your app (called adding a "configuration") through the Oauth process (same you use to install your app to a workspace), which allows your app to collect and store those tokens for later use.
Update: This doesn't work. It impersonates the user who installed the app, so it merely seems to work... until another user tries to use it (and they end up impersonating you).
Go to your App's management page. Select "OAuth & Permissions".
Add the chat.write OAuth Scope to your app as a User Token Scope, not a Bot Token scope.
Take note of your User OAuth Token at the top of this page (not your But User OAuth Token).
Call chat.postMessage with
username = user id of the user you'd like to post on behalf of
token = the token from step 3. above
The resulting post will be 100% impersonated. Not just the name and icon as mentioned in other answers, but it'll 100% function as if it came from the user.
I hope this will help those who are still facing this issue.
First give the chat:write and chat:write.customize scope to your bot. The scope chat:write.customize Send messages as #your_slack_app with a customized username and avatar
From "OAuth & Permissions" settings get the bot OAuth token or even bot access token (both will work).
Then set the arguments like the following.
username to specify the username for the published message.
icon_url to specify a URL to an image to use as the profile photo alongside the message.
icon_emoji to specify an emoji (using colon shortcodes, eg. :white_check_mark:) to use as the profile photo alongside the message.
You can visit the docs from here

Facebook Graph API won't return email address

Edit: Not Duplicate, because:
I have the permission
Debugged the token
Code works with test user
Please don't mark as duplicate without reading.
I'm trying to get the user e-mail address, but i don't get it. On graph api explorer, when i hit send, email field becomes grayed and says that:
field is empty or disallowed by access token
But when I debug the token it has email permission granted
My profile has an e-mail address.
Update: I tried https://developers.facebook.com/tools/console/ . My profile returns nothing, even on another computer. But the same code returns the email, name and uid of another account.
Code:
<fb:login-button scope="email">
Grant Permissions to make more examples work
</fb:login-button>
<button onclick="doPost()">Post to Stream</button>
<script>
function userData() {
FB.api('/me?fields=name,email', Log.info.bind('/me callback'));
};
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
userData();
}
});
</script>
It is possible to lockdown you e-mail so no one can has it? Even when i grant permission?
The Marcus' answer leads me to the real problem I was facing.
Debugging with the Facebook Explorer tool I was able to figure out that I should set the email scope at the FB.api() method after a successful login.
FB.login(function(response) {
if (response.status === 'connected'){
FB.api('/me?fields=id,email,name', function(data) {
console.log( data.email ) // it will not be null ;)
})
}, {scope: 'email'});
It is not quite clear at the Quickstart guide and I hope it helps someone else, too.
I had the same problem and I think I found out why:
If the user has an unconfirmed email in Facebook (i.e. Facebook sent him a validation mail to his email address but he didn't respond) Facebook WILL NOT pass that email to your app even if he gave you the email permissions (!!!).
So what I did is use his Facebook email if he has a user name (i.e. userName#facebook.com).
After i got my bug report marked as duplicate, and i read all posts and links there, i got what caused this problem for me and how to fix.
The Problem
Facebook seems to sometimes forget what your primary e-mail is on the graph API (But it still there in the preferences.)
Solution
The user affected must remove the e-mail, save settings, then re-add the address, re-confirm, then make it primary. This fixed my account both on my sandbox app, and other apps where Facebook login don't used to work.
New facebook graph requires scopes added in the /me request as follow:
/me?fields=email,birthday,location,locale,age_range,currency,first_name,last_name,name_format,gender&access_token=
I had the same issue while I was developing the fb login button for my site. I had even setup permissions for my app here:
https://developers.facebook.com/apps/<my-app-ID>/permissions
and it was working fine for certain initial cases, that is, it was giving email (i tested it on my own account and it was giving my email). Then suddenly it started to reflect no email at all. After two hours of browsing, I figured it out that there was an issue with the access token as when I went on this link:
https://developers.facebook.com/tools/explorer/<your-fb-id>/?method=GET&path=100002451127858%3Ffields%3Did%2Cemail
Update your-fb-id with your id and go to the above link. Click on 'Get Access Token'. In the tab that opens up, click on 'Extended Permissions' and in that, choose 'email' and submit. Now, test your query again. It'll definitely work, on the console as well as your website. Cheers! :)
This is a known bug. If the user does not have any email address set to primary, the query will return null for email. Set the email address for your account to primary https://www.facebook.com/settings?tab=account&section=email&view and then try.
Source: https://developers.facebook.com/bugs/298946933534016/

Categories

Resources