How can I reauthenticate with Facebook after the OAuth 2.0 changes to the sdk? - facebook-javascript-sdk

In our app we had some actions that we required the user to reauthenticate before proceeding. We used code like below to make this happen.
FB.login(
function(response) { /* code here */ },
{auth_type: 'reauthenticate', auth_nonce: '...'}
);
It looks like the auth_type option is no longer supported, because I am getting the following log message: 'FB.login() called when user is already connected.' and the user is not being asked to reauthenticate.
Does anyone have any ideas how to reauthenticate after the changes for OAuth 2.0?

It appears that, for the time being (and I qualify that because Facebook seems to change their API response on a whim), you can get auth_type: reauthenticate to work properly IF you also specify permissions (the scope parameter in OAuth 2.0). Check out this example:
http://www.fbrell.com/saved/a78ba61535bbec6bc7a3136a7ae7dea1
In the example, click Run Code, and then try the "FB.login()" and "FB.login() with Permissions" buttons. Both are coded to use auth_type: reauthenticate, but only the latter actually gives you the FB prompt once you are logged in.
Here are the relevant examples:
// DOES NOT PROMPT
document.getElementById('fb-login').onclick = function() {
FB.login(
function(response) {
Log.info('FB.login callback', response);
},
{ auth_type: 'reauthenticate' }
);
};
// PROMPTS AS EXPECTED
document.getElementById('fb-permissions').onclick = function() {
FB.login(
function(response) {
Log.info('FB.login with permissions callback', response);
},
{ scope: 'offline_access', auth_type: 'reauthenticate' }
);
};
So, the answer is, Yes, auth_type: reauthenticate DOES work, but ONLY if you also specify a valid scope parameter. (And yes, I tried it with an empty scope, and it acted the same as not using scope at all.)

You can use an iframe to make sure the cookie is always valid.
facebook auto re-login from cookie php

Using FacebookRedirectLoginHelper::getReAuthenticationUrl everything works fine.
Internally the method put 'auth_type' => 'reauthenticate' and pass also all the permissions required.
Now the issue is that only prompt to the user to re-enter the password without the possibility to "switch" between users or without the possibility to insert also the username.
Does someone found a solution for this issue?
I manage an application with multi accounts and when the user need to generate again the token this is an issue :(
Thanks, Alex.

Related

Why is my implementation of SSO using Ember-Simple-Auth with Auth0 getting stuck in a redirect loop?

I have an ember application that uses the Auth0 Ember Simple Auth addon to use the Ember-Simple-Auth functionality with Auth0's Lock.js. Recently I have been trying to implement single-sign-onfunctionality, such that if a user logs into a login portal application, their session will be preserved for other applications on the same domain, and they will not need to log in repeatedly. However my implementation of SSO is resulting in an infinite redirect loop between my login logic and Auth0's endpoint.
I have enabled SSO in the Auth0 application settings. My login is implemented in a few blocks.
My route.js contains a beforeModel() method which contains:
if (!get(session, 'isAuthenticated')){
// Forward to the login action
}
My login action:
login() {
var session = get(this, 'session');
session.authenticate('authenticator:myauthenticator', { authParams: { scope: 'openid' } });
}
This grabs the session object, and calls my custom authenticator. So far, this is basically just ember-simple-auth boilerplate, and complies with the examples supplied in the Auth0 Ember-Simple-Auth documentation.
Where I run into trouble is my custom authenticator. The base authenticator is here. You can see that it handles basic login logic easily, including showing the Auth0 lock when a user isn't authenticated. However it has no logic for handling the kind of SSO-session checking that I want to implement. So I implemented a custom authenticator as below, using examples provided by Auth0 for (basically) this exact scenario (you can see their examples [here], I'm using a slightly altered version)3:
authenticate(options) {
return new Ember.RSVP.Promise((res) => {
// the callback that will be executed upon authentication
var authCb = (err, profile, jwt, accessToken, state, refreshToken) => {
if (err) {
this.onAuthError(err);
} else {
var sessionData = { profile, jwt, accessToken, refreshToken };
this.afterAuth(sessionData).then(response => res(this._setupFutureEvents(response)));
}
};
var lock = this.get('lock');
// see if there's a SSO session available
lock.$auth0.getSSOData(function(err, data) {
if (!err && data.sso) {
// there is! redirect to Auth0 for SSO
options.authParams.callbackOnLocationHash = true;
lock.$auth0.signin(options.authParams, authCb);
} else {
// regular login
lock.show(options, authCb);
}
});
});
}
This behaves mostly as I would expect it to. When I log in with an existing session from another SSO-enabled app on the same domain, if (!err && data.sso) resolves to true, and lock.$auth0.signin(options.authParams, authCb) is called. However, this signin logic is not working as intended. Auth0.signin calls the Auth0.authorize method, which generates a target URL that looks something like:
https://mydomain.auth0.com/authorize?scope=openid&response_type=token&callbackOnLocationHash=true&sso=true&client_id=(MyClientIdHash)&redirect_uri=localhost%23access_token%3(MyAccessToken)%26id_token%3(MyIdToken1).(MyIdToken2).(MyIdToken3)token_type%3DBearer&auth0Client=(MyAuth0Client)
My application is then redirected to this URL for authorization. I get a 302 and am redirected back to the callback URL (my root page). Because there is a new page transition, if (!get(session, 'isAuthenticated')) is hit again. It returns false, and so the same logic repeats itself, looping indefinitely.
Does anyone have any insight on what I might be doing incorrectly here? The authorize endpoint seems to behave as if I were being authenticated, but then the authentication is never actually triggered. I've debugged through this code fairly extensively but seen no obvious red flags, and I've followed provided examples closely enough that I'm not sure what I would change. I'm not entirely sure where the failure to authenticate is happening such that get(session, 'isAuthenticated') is false.

auth0 remember last login never work for iOS

I have an ionic/angular 1.x application. I use Auth0 (auth0.com) to authenticate my users. When I was testing my app on the browser (using ionic serve), the auth0 can remember my last logged-in user credential. However, when I deploy my app to a real device (iPhone), Auth0 wants me to type in user credential (username+password) every single time.
I tried to add rememberLastLogin: true, in my auth.signin() method, but it never work. Below is my code snipped: I am wondering if anyone ever ran into the same situation and can give me some direction that I can check. Thank you very much!
auth.signin({
onestep: true,
showIcon: true,
rememberLastLogin: true,
signupFooterText: "this line won't appear..",
signupTitle: "don't show",
icon: "http://icons.iconarchive.com/icons/trysoda/soda-red/256/Keys-icon.png",
authParams: {
scope: 'openid offline_access' // set the refresh token here
}
}

Using Everyauth/Passport.js to authenticate with Twitter whilst asking for username/email/password

I want to create an authentication system whereby the user can "sign up with Twitter", but all this effectively does is authenticate their Twitter account and prefills a registration form with their Twitter username. The user will then be asked to enter an email and password (or an alternative username).
Thus, upon registration, the user has authenticated access to their Twitter account, and the access token can be stored in a database. Later down the line I will use this to access the Twitter API.
Node modules such as everyauth and passport do a lot of the heavy lifting with OAuth, but they only appear to provide a findOrCreateUser method, which doesn't offer a lot of breathing space to do something like what I need to do – that is, redirect to a registration form before registering the user, or if a user is found, just logging them in as per usual.
Here's a quick sketch of a possible approach for this:
Note that Passport does not provide a findOrCreateUser method. All database management and record creation is defined by your application (as it should be), Passport simply provides facilities for authentication.
The key to this approach is to simply create an "incomplete" user record in your database, from the profile data given by twitter. Then, in your application's routes, you can check if the conditions you need are met. If not, redirect the user to a form where they are prompted to fill out missing details.
passport.use(new TwitterStrategy({
consumerKey: TWITTER_CONSUMER_KEY,
consumerSecret: TWITTER_CONSUMER_SECRET,
callbackURL: "http://127.0.0.1:3000/auth/twitter/callback"
},
function(token, tokenSecret, profile, done) {
// Create a user object in your database, using the profile data given by
// Twitter. It may not yet be a "complete" profile, but that will be handled
// later.
return done(null, user);
}
));
app.get('/auth/twitter',
passport.authenticate('twitter'));
app.get('/auth/twitter/callback',
passport.authenticate('twitter', { failureRedirect: '/login' }),
function(req, res) {
// The user has authenticated with Twitter. Now check to see if the profile
// is "complete". If not, send them down a flow to fill out more details.
if (req.user.isCompleteProfile()) {
res.redirect('/home');
} else {
res.redirect('/complete-profile');
}
});
app.get('/complete-profile', function(req, res) {
res.render('profile-form', { user: req.user });
});
app.post('/update-profile', function(req, res) {
// Grab the missing information from the form and update the profile.
res.redirect('/home');
});
Slight clarification. The test "if (req.user.isCompleteProfile())" could be:
if (req.user.isCompleteProfile)
ie, you create a field 'isCompleteProfile' when you are making the user record in the twitter step, and mark it true or false, depending on what you know of the user
or: it is a call to a function, thus
if (isCompleteProfile(req))
in this case, you have a separate function which tests the state of the user you have just created/modified, thus:
function isCompleteProfile(req) {
if (typeof req.user.local.email === "undefined") return false;
else return true;
}
And, I'd echo the praise for Jared and this marvellous tutorial on authentication in passportjs.

Firebase password resets

I'm trying to create a password reset mechanism and am stuck. Any suggestions how to do this with Firebase basic email/password authentication
[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://firebase.google.com/docs/.
Also, check out https://firebase.google.com/docs/auth/web/password-auth for the latest Firebase Simple Login - Web Client docs.
This is something that Firebase doesn't do very well. As you'll notice it requires the user to remember their old password. Usually if you want to reset a password it's because you've forgotten it. Hopefully the improve the methods they provide for account management.
https://www.firebase.com/docs/security/simple-login-email-password.html
authClient.changePassword(email, oldPassword, newPassword, function(error, success) {
if (!error) {
console.log('Password change successfully');
}
});
This was the first google result that came up when trying to figure out my issue.. for anyone who uses yeoman angularfire generator but would like to add the send email feature, this should work.
add the following to the simple login factory in simpleLogin.js:
resetPassword: function(emailIn){
return auth.$resetPassword({
email: emailIn
}, function(error) {
if (error) {
switch (error.code) {
case "INVALID_USER":
console.log("The specified user account does not exist.");
break;
default:
console.log("Error resetting password:", error);
}
} else {
console.log("Password reset email sent successfully!");
}
});
},
and call it from your login.js file
$scope.resetPassword = function(email){
simpleLogin.resetPassword(email)
};

Google+ signin button - unable to make authenticated calls

I am adding the new Google+ signin button to my app and having some problems with making authenticated calls. I have included the html and javascript as described in the docs and the signin works. I have can even see the access token. However when I make a request to an authenticated endpoint I get an "invalid credentials" response. For example I am attempting:
gapi.client.oauth2.userinfo.get().execute(function(resp){console.log(resp);});
I can make this call if I use the regular google oauth methods ( gapi.auth.authorize()).
What is going on here? what am I doing wrong?
I am requesting the userinfo.email and userinfo.profile scopes with the google+ button.
Html for G+ signin:
<span id="signinButton">
<span
class="g-signin"
data-callback="signinCallback"
data-apppackagename="com.mypackage"
data-clientid="myclientID"
data-cookiepolicy="single_host_origin"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-scope="https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/devstorage.read_only https://www.googleapis.com/auth/plus.login">
js included for G+ signin button(just before ):
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/client:plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
callback for G+ button:
function signinCallback(authResult) {
if (authResult['access_token']) {
signin();
} else if (authResult['error']) {
console.log('There was an error: ' + authResult['error']);
}
}
Request for userprofile:
gapi.client.oauth2.userinfo.get().execute(function(resp) {console.log(resp);});
The request includes the Authorization header with a token(seen through chrome dev tools).
Update:
I have also attempted using gapi.auth.authorize() in immediate mode. This did not work for and returned a null response. When I ran this with immediate mode set to false, I was presented with the authorization prompt (again, after authorizing with g+ button). After this my authorized calls worked. Below is my code:
gapi.auth.authorize({client_id: 'myClientID', scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/devstorage.read_only',
immediate: mode, response_type: 'token id_token'}, callback);
I built a repro of your use case and documented it in this gist, it's working fine for me. Some other notes:
if you request plus.login, you shouldn't request userinfo.profile because it's included as part of plus.login and would create duplicate permissions in the authorization dialog. You can find more on this in the best practices section of the docs.
you should use
data-apppackagename only to provide the package for a valid android application, otherwise you might trigger 500 errors in the auth dialog.
The first thing to check is to make sure you're requesting the scopes that gapi.client.oauth2.userinfo is looking for. You can request additional scopes as part of the button.
Use the network console in something like Chrome to see if there is an Authorized: header passed along with the request and what it might be. If it isn't sent or is undefined, the token itself may not have been set, in which case you might need to set the auth token with gapi.auth.setToken() as documented at https://code.google.com/p/google-api-javascript-client/wiki/ReferenceDocs or just call gapi.auth.authorize in immediate mode with the same scopes, which should make sure it gets the token.
I have done the google authentication by using OAuth2Authenticator in android xamarin. steps might be helpful to you.
1.register in google developer console as webapplication instead of installed application(android)* provide the redirect url with valid url ("http://abcd.com/xyz.aspx") same should be used in the application code.
2.on authentication complete it will return access_token
3.by using the access_token make the REST request to get user complete information (https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + accessTokenValue + “.)
4.Deserialize the json response to get information in object.
check more here :Google Account login Integration for android Xamarin