How to verify users current password? - firebase

So, maybe I missed this somewhere in the docs but I couldn't find anything of the sort.
I wan't my users to have to type in their current password to be able to create a new one. From what I understand if the user is authenticated he is able to update his password without providing his current one.
Even if this might be somewhat secure I would rather have him type his old one to prevent people from going on already authenticated sessions from say family members or so and changing the pw.
Is there any way to do this?
(I have no problem using the Admin SDK since I already set up a server for these kind of things)

UPDATE: (Use - reauthenticateWithCredential)
var user = firebaseApp.auth().currentUser;
var credential = firebase.auth.EmailAuthProvider.credential(
firebase.auth().currentUser.email,
providedPassword
);
// Prompt the user to re-provide their sign-in credentials
user.reauthenticateWithCredential(credential).then(function() {
// User re-authenticated.
}).catch(function(error) {
// An error happened.
});
PREVIOUS VERSION
you can use reauthenticate API to do so. I am assuming you want to verify a current user's password before allowing the user to update it. So in web you do something like the following:
reauthenticateAndRetrieveDataWithCredential- DEPRECATED
firebase.auth().currentUser.reauthenticateAndRetrieveDataWithCredential(
firebase.auth.EmailAuthProvider.credential(
firebase.auth().currentUser.email,
providedPassword
)
);
If this succeeds, then you can call
firebase.auth().currentUser.updatePassword(newPassword);

Related

Wordpress API to authorize a user

Is there some API in Wordpress to 'authorize' a user? Let's say I want to implement something like:
if (1 == 1) {
user_authenticate('userXY');
}
The method user_authenticate would initialize the session and send the necessary cookies to the user.
Thank you!
There are a number of built-in WordPress functions that you may find helpful for what you're trying to do. I'm guessing the most helpful would be the wp_set_auth_cookie function (See: https://developer.wordpress.org/reference/functions/wp_set_auth_cookie/).
You may want to try something like:
wp_clear_auth_cookie();
$user = get_user_by('login', $username);
$user_id = $user->ID;
wp_set_auth_cookie($user_id);
wp_set_current_user($user_id);
or something to that effect.
Here are some other user/cookie/session functions available to you:
In the wp-includes/pluggable.php file
wp_validate_auth_cookie - Validates authentication cookie.
wp_generate_auth_cookie - Generates authentication cookie contents.
wp_parse_auth_cookie - Parses a cookie into its components.
wp_set_auth_cookie - Sets the authentication cookies based on user ID.
wp_clear_auth_cookie - Removes all of the cookies associated with authentication.
wp_get_current_user - Retrieve the current user object.
wp_set_current_user - Changes the current user by ID or name.
In the wp-includes/user.php file
wp_get_session_token - Retrieve the current session token from the logged_in cookie.
wp_get_all_sessions - Retrieve a list of sessions for the current user.
wp_destroy_current_session - Remove the current session token from the database.
wp_destroy_other_sessions - Remove all but the current session token for the current user for the database.
wp_destroy_all_sessions - Remove all session tokens for the current user from the database.
There is also a great plugin (only one file long) that does this sort of thing called User Switching (See: https://wordpress.org/plugins/user-switching/). You may also find some very helpful code from poking around that file.

Integrate API authentication to WordPress

I have a website where I have to authenticate the users registered in another system (in this case the Kayako support system).
I think I have to use the APIs to resolve this problem, but I don't really know how to get started.
Can someone please help me solve this problem? How can I send the data required for the authentication and how do I manage the response I get from Kayako.
Figure out how the API of the Kayako system looks like. In WordPress you can do something similar like this in order to authenticate the users:
// this action is executed just before the invocation of the WordPress authentication process
add_action('wp_authenticate','checkTheUserAuthentication');
function checkTheUserAuthentication() {
$username=$_POST['log'];
$password=$_POST['pwd'];
// try to log into the external service or database with username and password
$ext_auth = try2AuthenticateExternalService($username,$password);
// if external authentication was successful
if($ext_auth) {
// find a way to get the user id
$user_id = username_exists($username);
// userdata will contain all information about the user
$userdata = get_userdata($user_id);
$user = set_current_user($user_id,$username);
// this will actually make the user authenticated as soon as the cookie is in the browser
wp_set_auth_cookie($user_id);
// the wp_login action is used by a lot of plugins, just decide if you need it
do_action('wp_login',$userdata->ID);
// you can redirect the authenticated user to the "logged-in-page", define('MY_PROFILE_PAGE',1); f.e. first
header("Location:".get_page_link(MY_PROFILE_PAGE));
}
}
The try2AuthenticateExternalService() method should contain some curl-request (or similar) to the remote service.

New user email verification [duplicate]

Question says it all. In Firebase, how do I confirm email when a user creates an account, or, for that matter, do password reset via email.
I could ask more broadly: is there any way to send emails out from Firebase? E.g. notifications, etc. This isn't the kind of thing you would usually do client-side.
Update
Note that this was never a very secure way of handling email verification, and since Firebase now supports email verification, it should probably be used instead.
Original answer
I solved the email verification using the password reset feature.
On account creation I give the user a temporary (randomly generated) password. I then trigger a password reset which will send an email to the user with a link. The link will allow the user to set a new password.
To generate a random password you can use code similar to this:
function () {
var possibleChars = ['abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!?_-'];
var password = '';
for(var i = 0; i < 16; i += 1) {
password += possibleChars[Math.floor(Math.random() * possibleChars.length)];
}
return password;
}
Note that this is happening on the client, so a malicious user could tamper with your logic.
This would need to be done outside of firebase. I store users at /users/ and keep a status on them (PENDING, ACTIVE, DELETED). I have a small service that monitors users of a PENDING status and sends out a confirmation email. Which has a link to a webservice I've created to update the user status to ACTIVE.
[Engineer at Firebase - Update 2014-01-27]
Firebase Simple Login now supports password resets for email / password authentication.
Each of the Simple Login client libraries has been given a new method for generating password reset emails for the specified email address - sendPasswordResetEmail() on the Web and Android, and sendPasswordResetForEmail() on iOS.
This e-mail will contain a temporary token that the user may use to log into their account and update their credentials. This token will expire after 24 hours or when the user changes their password, whichever occurs first.
Also note that Firebase Simple Login enables full configuration of the email template as well as the sending address (including whitelabel email from your domain for paid accounts).
To get access to this feature, you'll need to update your client library to a version of v1.2.0 or greater. To grab the latest version, check out https://www.firebase.com/docs/downloads.html.
Also, check out https://www.firebase.com/docs/security/simple-login-email-password.html for the latest Firebase Simple Login - Web Client docs.
As at 2016 July, you might not have to use the reset link etc. Just use the sendEmailVerification() and applyActionCode functions:
In short, below is basically how you'll approach this, in AngularJS:
// thecontroller.js
$scope.sendVerifyEmail = function() {
console.log('Email sent, whaaaaam!');
currentAuth.sendEmailVerification();
}
// where currentAuth came from something like this:
// routerconfig
....
templateUrl: 'bla.html',
resolve: {
currentAuth:['Auth', function(Auth) {
return Auth.$requireSignIn() // this throws an AUTH_REQUIRED broadcast
}]
}
...
// intercept the broadcast like so if you want:
....
$rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
if (error === "AUTH_REQUIRED") {
$state.go('login', { toWhere: toState });
}
});
....
// So user receives the email. How do you process the `oobCode` that returns?
// You may do something like this:
// catch the url with its mode and oobCode
.state('emailVerify', {
url: '/verify-email?mode&oobCode',
templateUrl: 'auth/verify-email.html',
controller: 'emailVerifyController',
resolve: {
currentAuth:['Auth', function(Auth) {
return Auth.$requireSignIn()
}]
}
})
// Then digest like so where each term is what they sound like:
.controller('emailVerifyController', ['$scope', '$stateParams', 'currentAuth', 'DatabaseRef',
function($scope, $stateParams, currentAuth, DatabaseRef) {
console.log(currentAuth);
$scope.doVerify = function() {
firebase.auth()
.applyActionCode($stateParams.oobCode)
.then(function(data) {
// change emailVerified for logged in User
console.log('Verification happened');
})
.catch(function(error) {
$scope.error = error.message;
console.log(error.message, error.reason)
})
};
}
])
And ooh, with the above approach, I do not think there's any need keeping the verification of your user's email in your user data area. The applyActionCode changes the emailVerified to true from false.
Email verification is important when users sign in with the local account. However, for many social authentications, the incoming emailVerified will be true already.
Explained more in the article Email Verification with Firebase 3.0 SDK
What I did to work around this was use Zapier which has a built in API for firebase. It checks a location for added child elements. Then it takes the mail address and a verification url from the data of new nodes and sends them forwards. The url points back to my angular app, which sets the user email as verified.
As I host my app files in firebase, I don't need have to take care of any servers or processes doing polling in the background.
There is a delay, but as I don't block users before verifying mails it's ok. Zapier has a free tier and since I don't have much traffic it's a decent workaround for time being.
The new Firebase SDK v3 appears to support email address verification, see here (put your own project id in the link) but it doesn't appear to be documented yet.
I have asked the question on SO here
See #SamQuayle's answer there with this link to the official docs.
As noted by various others Firebase does now support account related emails but even better, as of 10 days ago or so it also supports sending any kind of email via Firebase Functions. Lots of details in the docs and example code here.
I used following code to check the email verification after creating new account.
let firAuth = FIRAuth.auth()
firAuth?.addAuthStateDidChangeListener { auth, user in
if let loggedUser = user {
if loggedUser.emailVerified == false {
loggedUser.sendEmailVerificationWithCompletion({ (error) in
print("error:\(error)")
})
}
else {
print(loggedUser.email)
}
} else {
// No user is signed in.
print("No user is signed in.")
}
}
I used MandrillApp. You can create an API key that only allows sending of a template. This way even thought your key is exposed it can't really be abused unless someone wants to fire off tonnes of welcome emails for you.
That was a hack to get myself off the ground. I'm now enabling CORS from a EC2 that uses the token to verify that the user exists before extending them a welcome via SES.

How can I create a method for retrieving user email address that is available on the client and server?

I've got facebook, google and regular registration/login turned on on my website. The problem I have is that the email address is stored in different fields depending on how the user first joined.
For regular users, it is in field emails[0].address. For facebook and google authenticated users it is in field services[0].email.
At various places in the client (templates, events) and on the server (method), I just want to call one method that works out which field to use and returns the email address. I also want to do something similar for the verification field.
I'm fairly new to meteor and the only ways I've found to do the above so far is to repeat the same logic in the client and on the server which doesn't sit well with me.
The best thing to do would be to transfer the email address to 'emails' if they log in with facebook, google or another services for the first time. This would also make it more future proof incase you add other services, since meteor will always use emails.address (including in other packages)
Server side code:
Accounts.onCreateUser(function(user) {
user.emails = user.emails || []; //If its null set it to an empty array
if(user.services.facebook) {
user.emails.push({address: user.services.facebook.email, verified: false});
}else if(user.services.google) {
user.emails.push({address: user.services.google.email, verified: false});
}
return user;
});
Then you can just check Meteor.user().emails[0].address every time.
Note: If not published due to the autopublish package you may have to publish the emails field for it to work on the client.
You may also have to run this the first time for users who have already logged in before:
Meteor.startup(function() {
Meteor.users({'emails':{$exists: false}}).fetch().forEach(function(user) {
var email = (user.services.facebook || user.services.google).email;
if(email) Meteor.users.update({_id: user._id},{$push:{emails:{address: email, verified: false}}});
});
});
I'm not sure if facebook and google both use email in the services key, if they do the above should work fine. If they don't you can edit out the key that is used for google or facebook, in case one is emailAddress instead of email for example.

ACS - bypassing user redirection to IdP?

I have only recently been looking into ACS, AAL, WAAD and I would like to avoid redirecting users to the login page of their IDP. I want to keep my users within my site and present them with a dropdown to choose who they wish to authenticate with and an area to request a username and password, then acquire token via code. Is this possible?
I have been reviewing some sample applications and produce a quick mock-up, but cant seem to get things working e.g.
_authContext = new AuthenticationContext("https://littledeadbunny.accesscontrol.windows.net");
string enteredEmailDomain = UserNameTextbox.Text.Substring(UserNameTextbox.Text.IndexOf('#') + 1);
IList<IdentityProviderDescriptor> idpdList = _authContext.GetProviders("http://littledeadbunny.com/NonInteractive");
foreach (IdentityProviderDescriptor idpd in idpdList)
{
if (String.Compare(ServiceRealmDropDownList.SelectedValue, idpd.Name, StringComparison.OrdinalIgnoreCase) == 0)
{
Credential credential;
credential = new UsernamePasswordCredential(enteredEmailDomain, UserNameTextbox.Text, PasswordTextbox.Text);
_assertionCredential = _authContext.AcquireToken("http://littledeadbunny.com/NonInteractive", idpd, credential);
return;
}
}
Using the code above, when I try to use the Windows Azure Active Directory User (admin), i get the error "Data at the root level is invalid. Line 1, position 1." where I attempt to acquiretoken.
When I use Google, I get an error "0x8010000C: No identity provider matches the requested protocol".
If there is a working sample? if I am doing something obviously wrong, I would appreciate the correction.
This is not supported for passive identity providers. IdPs like Google, Facebook, etc. don't want other people collecting credentials for them, as this leads to security issues and possible phishing attacks. They also don't support it because they need to be able to show a permission dialog (that screen that asks the user if they want to release data to you) which they can't do without the browser redirecting to them. Furthermore, Google in particular supports two-factor auth, which you couldn't replicate, and generally collecting credentials opens up whole cans of worms around other UI problems such as incorrect or forgotten passwords.
This is also generally a bad user experience, because your users are fairly likely to already be logged in to Google and have cookies there. If so, and if they've already consented to your app, they would just be silently redirected back to you. In your scenario, even if the user is already logged in they'd still have to provide a username/password.
The correct way to do these sorts of logins is to render a browser control in your app that allows the user to log in at their IdP, which is what AAL helps with.
I had the same error, executing a powerscript solved that error
PS C:\windows\system32> $replyUrl = New-MsolServicePrincipalAddresses
-Address https://mydomain.accesscontrol.windows.net/
PS C:\windows\system32> New-MsolServicePrincipal -ServicePrincipalNames
#("https://mydomain.accesscontrol.windows.net/") -DisplayName
"MyDomain Namespace" -Addresses $replyUrl
But i'm stuck anyway with a 403 permission error
If you get any further i would like to know how :)

Resources