Hijacking the Meteor accounts-ui logout button - meteor

I am using the accounts-ui package for Meteor to create a Sign-up/Log-in widget. I want users who are not signed in to be able to continue to use my app anonymously, so I want to detect when a user signs out.
As far as I can tell, there is a way to register a function when the user logs in but no similar event is triggered when the user logs out. The next best thing is the Meteor.logout(\[callback\]) command, which accepts a callback function.
I have found the following lines of code in /Users/<name>/.meteor/packages/accounts-ui-unstyled/.1.1.8.cfkrwq++os+web.browser+web.cordova/web.browser/login_buttons.js
Template.loginButtons.events({
'click #login-buttons-logout': function() {
Meteor.logout(function () {
loginButtonsSession.closeDropdown();
});
}
});
I want to add a call to a method of my own here, but I don't want this method to be called in all the projects where I use accounts-ui. I understand that I could copy the accounts-ui-unstyled/ folder to the packages folder at the root of this project, and modify it there, but then I will miss any updates that may be delivered for the package.
What is the best-practice method of intercepting the log-out call?

Another approach is just to track the logged-in state in a Tracker:
Tracker.autorun(function(){
if ( Meteor.userId() ){
... do things for a logged-in user
} else {
... do things for a logged-out user
}
});
This autorun block will run automatically whenever the login state changes as Meteor.userId() is a reactive data source.

Related

Meteor Iron Router Login Route Pass-thru for Facebook accounts not working

The Issue:
When my regular users using the standard email/password 'accounts-password' go to a login redirected page , they can enter the credentials and the router will proceed to render the requested page.
For example:
/private_page (requires login). The user attempts to go to http://foo.com/private_page they are presented with the Login page. The user enters username/password correctly and now the /private_page displays.
This works, what does NOT work...
Same example as above, but now the user is authenticating with Facebook 'accounts-facebook'. Everything is the same as before and the user has succesful login with Facebook and is able to get into my web application except the route never displays the /private_page. It stays on the authenticated /login page without showing the login template.
IN A NUTSHELL
How do I make the facebook authenticated users pass-thru and route to the requested route like the regular password based users operate ?
Iron Router Config:
Router.onBeforeAction(function () {
if (!Meteor.userId() && !Meteor.loggingIn()) {
this.redirect('login');
this.stop();
} else {
this.next();
}
},{except: ['login', 'contact, 'terms']});
Meteor packages:
accounts-password#1.3.6
accounts-facebook#1.2.0
service-configuration#1.0.11
useraccounts:bootstrap
useraccounts:iron-routing
I finally came to a solution.
After reviewing the Github issues for the Meteor package: (meteor-useraccounts)I found the exact issue I have been having.
https://github.com/meteor-useraccounts/core/issues/685
I spent too much time trying to make the hooks fire correctly for my usage of oAuth Facebook with Meteor. My final solution was too just connect directly into the Meteor method calls and create my own login, registration, password reset, etc forms.
The up-side is that I now have full control of the forms and I don't need to deal with extra package.
If anyone comes finds this posting and is having issues making 'meteor-useraccounts' fire hooks like the postSignUpHook , you may decide to just scrap the package and make your own user account templates and connect the logic to use the native Meteor methods.
This particular question I submitted was because the oAuth Facebook would login but I was unable to make it redirect to the originally requested route. The oAuth works and my user can login to my web app, but I cannot get them to the originally requested url.
How did I solve this:
lib/routes
Router.onBeforeAction(function () {
if (!Meteor.userId() && !Meteor.loggingIn()) {
originalUrl = this.originalUrl;
this.redirect('login');
this.stop();
} else {
this.next();
}
},{except: ['login', 'resetPwd', 'help'] });
The key point to take away from the snippet above is the global variable I declare originalUrl. This is using the routers this.originalUrl. This url contains the original url that the user entered and is captured the moment before the iron-router redirects to the login page.
Now on the login page I created my two different login methods using my own custom template. They both are using the Meteor.loginWithPassword and Meteor.loginWithFacebook methods.
client/login.js
'click #fb-login' : function(e){
e.preventDefault();
Meteor.loginWithFacebook({}, function(err){
if(err) {
// some error occured
}
else {
if(Router.current().route._path == "/login" && typeof originalUrl == "undefined")
Router.go('/');
else
Router.go(originalUrl);
}
});
}
Hope this helps anyone else who might come across this issue.

Accounts.onLogin how to get user Id?

How do you get the _id of the user that logged in. I have tried the following combinations and I get errors, or undefined
Upon user creation, the user is automatically signed into the application. Is the user that is returned by the Accounts.onCreateUser function occurring after the user is logged in?
Accounts.onLogin(function(){
var user = this.userId / Meteor.user() / Meteor.user()._id
console.log(user)
})
http://docs.meteor.com/#/full/accounts_onlogin
The Accounts.onLogin(function(){}), come with 1 parameter user.
When it is known which user was attempting to login, the Meteor user
object. This will always be present for successful logins.
from the docs.
So this should work.
Accounts.onLogin(function(user){
console.log(user.user._id)
});
And you should see, all the user document into the server console,check this meteorpad for an example.
NOTE: this feature is only available on server side check this Hooks Accounts.onLogin/onLoginFailure should be available on client
You can always get the _id of the logged-in user via Meteor.userId(). This also works inside the Accounts.onLogin callback
Accounts.onLogin(function() {
console.log(Meteor.userId());
})

Meteor user permissions

I'am trying to check the users permission (roles) in the routing (iron routing). I have a boolean property in the user which I set in the
Accounts.onCreateUser
e.g. isvalid = false. The first problem is that only username and id are exposed so I try too publish
Meteor.publish('userData',function() {
return Meteor.users.find({_id:this.userId},{fields:{'isvalid':1}});
});
In the router I check
onBeforeAction: function() {
if(!Meteor.user() || !Meteor.user().isvalid)
this.render('nopermission');
else
this.next();
}
It works but when I debug I can see that the onBeforeAction fires three times. First time the user is undefined, second time I have a user without the property isvalid and third time I have everything. In debug I can see the screen flash with the template "nopermission" but when I run it live it seems ok. I think I have done it wrong, how can I check the permission in the correct way? I know that this code runs in client and I plan to do the check even on the server and I suppose that the Meteor.user().isvalid works without any problems on the server.
Thanks for help

Firebase authWithOAuthRedirect() woes

I'm trying to update my angularjs app to support Firebase 1.1 (I was stick with Firebase 1.0.x).
It deprecates firebasesimplelogin, including authentication inside Firebase core.
I have been able to successfully implement authentication using
authWithOAuthPopup("<provider>", function(error, authData) { ... });
It accepts a callback, which is passed authentication data in authData.
On the contrary, I can't undersand how to use
authWithOAuthRedirect("<provider>", function(error) { ... });
Firebase Authentication docs page is very concise... :-(. This is all what is said:
Alternatively [instead of authWithOAuthPopup], you may prompt the user to login with a full browser redirect, and Firebase will automatically restore the session when you return to the originating page
How do I get authData, when Firebase - after redirection - returns to my page?
The authData is available by registering a listener directly on the ref (so before calling authWithOAuthRedirect).
ref.onAuth(function(authData) {
...
}
ref.authWithOAuthRedirect("google", function(error) { ... });
See https://www.firebase.com/docs/web/guide/user-auth.html#section-monitoring-authentication
I think I'm running into the same issue as you. I'm trying to do Facebook authentication.
First, I'd like to clarify the reproduction steps for my issue.
My app is loaded on the client.
User clicks login with Facebook.
ref.authWithOAuthRedirect('facebook', ...) is called.
Client is redirected to Facebook and Facebook redirects client back to Firebase app
Despite successful authentication with Facebook, the callback passed to onAuth() is invoked (only once) with authData === null.
The callback passed to onAuth() is not invoked a second time with correct authData.
However, reloading the app causes the callback passed to onAuth to be invoked with correct authData. The reasons for this are not known to me but I suspect race condition.
Here's my workaround.
Before calling ref.authWithOAuthRedirect('facebook', ...) set yourself a flag in sessionStorage.
sessionStorage.reload = true;
ref.authWithOAuthRedirect('facebook', ...)
When the client is redirected to your app back from Facebook, you should be able to check for this flag and reload the page if necessary.
if (sessionStorage.reload) {
delete sessionStorage.reload;
setTimeout(function() {
location.reload();
}, 1000)
}
setTimeout(function() { ... }, 1000) helps fight the assumed race condition. I found 500 ms is insufficient time for the race condition to be resolved.
And one small gotcha: if you reload the page too soon, then authData remains null no matter how many times you reload the page.

wp_login and is_user_logged_in

I am developing an extension for a plugin and would like to run some code after every time a user logs in. Because I extend a plugin, I wanted to use the already written functions, which inside use is_user_logged_in() calls. If I register for the wp_login action and run is_user_logged_in in my action hook it returns false, which sounds really weird.
Code I was running:
add_action('wp_login', 'exhib_persist_cookies_after_login');
/*
* This method will persist the favorite posts from the cookies just after someone logs in.
*/
function exhib_persist_cookies_after_login() {
//Check if all the required functions are available
if (is_user_logged_in()) {
error_log("persist: USER LOGGED IN");
}
else {
error_log("persist: USER NOT LOGGED IN");
}
}
And in the log I see USER NOT LOGGED IN.
Anyone has a clue why is it happening? I thought is_user_logged_in is checking for the auth cookie, which is according to the doc is already set before wp_login is getting called.
Or anyone has an another idea what action should I register, which only fires once a user logged in and the is_user_logged_in returns there true?
Before you even look at why the modification isn't working, you should think about changing how you're modifying the plugin. Directly modifying a plugin is dangerous. It breaks the upgrade path preventing you from applying upgrades in the future which could resolve critical issues with the plugin itself. The same functionality could be achieved by creating a simple plugin that contains nothing but the code you want to run.

Resources