grails+spring-security-facebook listen to login success event - facebook

im a newbie both in spring security and spring-security-facebook and in an app that we are building we have to couple them.Everything is working well i will need to know the way to listen to the facebook login success event. is there some one that already did a stuff that impose him to catch the facebook event success?? I need that because in the begining of the app (before adding the spring -security-Facebook plugin ); we have a special behaviour attached to the "grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent" event (configured in the config.groovy file) and we have to execute the same special behaviour when the user connect with facebook account. Is there an event (extending springsecurity kinds of events) that we have to listen to?
any idea ??
Ps: when searching for solution we found a way to catch the FB js Events and work around to reach what we want as result but we would as possible to want to not go that way ....

The problem with it that current Spring Security Facebook authenticates user on each request (by listening to FB cookie, transparently), so you'll get this event on each request. Probably it's not what you want, right? It the same as having a filter on each request.
Btw, you can handle situation when user login into your app first time, but implementing onCreate(user, token) or afterCreate(user, token) in service FacebookAuthService (you have to create such service at this case)
Example:
File grails-app/services/FacebookAuthService.groovy:
class FacebookAuthService {
void afterCreate(def user, def token) {
log.info("New user!") //or any code there
}
}

Related

Are there web browser packages for flutter that allow for callbacks?

I'm tasked with integrating with a service (Terra) that implements launching a web view to log into said service. Once the user logs in, it returns a url with params I need for further processing. However, my problem is that once I'm logged in successfully, all I can do is close the web browser manually, and the url that I need can't be used at all.
I'll attempt to pseudo code this:
Create a widget that will hit the service's endpoint to retrieve a sessionId and their url
Receive the url and sessionId
Using the url that we received, use url_launcher to open the web view
In this web view, log in with credentials
Once successfully logged in and the web view is redirected, retrieve the new URL on the flutter side to process the new params.
Only the last step is a bit unknown to me and the rest is working. I'm not sure if I could use a Stream to listen to any changes with browser's url, nor am I sure if that would work at all.
Is there any way to achieve what I need?
There's no need to use url_launcher, as you can simply redirect to the login page with, for example:
html.window.open(uri, '_self');
That opens the login page in the same window where your Flutter web app was running, and your user proceeds to log in.
At the end of that flow, the auth server should redirect you to a URL of your choosing, which you set to the URL of your Flutter app (which you can calculate at run time with):
Uri.parse(html.window.location.href).removeFragment();
So, now you end up back running your main.dart again, but this time you have some extra parameters, which you grab immediately with:
Map<String, String>? initialQueryParameters;
void main() {
initialQueryParameters = Uri.parse(html.window.location.href).queryParameters;
runApp(SomeWidget());
}
Now at any point in your code you can inspect the initialQueryParameters to extract the response from the auth server which is normally simply added after the ? in the redirect URL back to you.

How to use new enhanced sessions in Parse with users created on cloud code?

I was trying out the new enhanced revocable sessions in Parse on my Android app. It works well when logging in or signing up via email password or facebook but doesn't work well for custom authentication, e.g. google+.
I'm currently logging in the user using the cloud code which also creates the new user when signing up. This does not create a new Session object, that means the new enhanced sessions are not used and it still uses the legacy sessions.
I pass the session token back to client where using the become method the user logs in but it's the legacy sessions.
This feels like the feature is not complete but I would really like to move to the new enhanced sessions with my app. Has anyone worked with them yet? Are there any workarounds using the REST API or by creating the sessions manually and handling them manually? I looked into the JS API but it says it's only read only.
Here's the Blog post on Enhanced Sessions.
Where should I go next?
Yes, I found a solution but it's a workaround, works for my case because I don't support signing up with user/password.
Basically, the solution (cloud code) in semi pseudo-code is:
Fetch the user with master key
Check if user.getSessionToken() has value
if it has, return the session token and do a user.become() in the client as usual
if it's not, here the workaround, do the following:
yourPreviousPromiseInOrderToChainThem.then(function(user)
password = new Buffer(24);
_.times(24, function(i) {
password.set(i, _.random(0, 255));
});
password = password.toString('base64')
user.setPassword(password);
return user.save();
}).then(function(user) {
return Parse.User.logIn(user.get('username'), password)
}).then(function(user) {
var sessionToken = user.getSessionToken();
// Return the session token to the client as you've been doing with legacy sessions
})
That means, I'm changing the user password each time in order to make a remote login and, of course, I know thist can't be applied to all cases, it's enough for app because I don't support login with user/password (only third party logins) but I understand that maybe it's not for all cases.
I got the idea from this official Parse example.
I don't like this solution because I think is not a workaround, it's a mega hack but I think there is no other way to do it currently (either Parse.com or Parse-Server)
If you find other workaround, please, share it :)

Facebook Logout not working(session always recreated). CakePHP + Facebook plugin

So, I've been at this for a while now, went through a bunch of different questions, and still no solution.
If I log in regularly, all is fine, I can logout as expected. But, if I login with facebook (authorize the app), then there is no way to logout unless I manually delete the cookies from within my browsers menu.
Following that logic, I wanted to destroy the cookies in the logout action using this code(after I modified my session settings to work across subdomains, for my particular case):
function logout() {
if ($this->Cookie->read('Auth.User')) {
$this->Cookie->delete('Auth.User');
}
$this->Auth->logout();
unset($_SESSION['fb_MYAPP_ID_user_id']);
unset($_COOKIE['fbm_MYAPP_ID']);
unset($_COOKIE['fbsr_MYAPP_ID']);
unset($_COOKIE['CAKEPHP']);
//pr($_SESSION);pr($_COOKIE);exit(); //here I see that the cookies are in fact deleted
$this->redirect($this->Auth->logout());
$this->redirect('/login');
}
But every time after the logout redirect it brings the user back, logged in, and the session/cookies recreated.
I went through a lot of SO questions and answers and none worked for me. Any ideas?
You cannot simply unset cookies from the cookie container, this is just the server side representation of the cookies contained in the request.
To delete cookies you need to set the exact same cookie (domain, path, name) but with an expiration that has passed - when read by the client this will cause the cookie to not be sent with the next request.
You can see how this is done in https://github.com/facebook/facebook-php-sdk/blob/master/src/base_facebook.php#L132.
I ended up using a combination of the following answers:
CakePHP + Facebook
$facebook->getSession() call breaks page below the call
The code on the first one is more complete, but is outdated. I also kept the unset() calls that I have in my question, and it seems to work good for now.

Using a WebViews cookies with an HTTP Client

This is with reference to using Google Contacts Data API.
It requires that the application gets authentication view a WebBrowser/WebView (in the case of android).
Therefore the RequestTokenUrl is passed to the webview which will show a Google Sign-in page and then ask the user if it allows the application to access their account.
Once authorized, there needs to be some kind of callback to the activity.
The activity will then use the WebViews cookie (which should contain the AccessToken) with an HTTP client to request data from Google Data API. This could be anything, in our case it is the Google Contacts.
Any ideas on how this can be done?
EDIT: Found another way around the problem by using OAuth 2.0.
This still required getting the AuthorizationCode from the WebView but that is accessed through the pagetitle instead of a cookie.
The selected answer still addresses the original question correctly.
The following code which uses the reflection library will print a line with the cookies:
Sub WebView1_PageFinished (Url As String)
Dim r As Reflector
r.Target = r.RunStaticMethod("android.webkit.CookieManager", "getInstance", Null, Null)
Log(r.RunMethod2("getCookie", Url, "java.lang.String"))
End Sub

FB.getLoginStatus not calling its callback

The title really says it all. Under some (undetermined) conditions FB.getLoginStatus() just stops working and won't invoke the callback I gave it. The only interesting clues I've found are
FB.Auth._loadState is stuck on "loading" -- whatever is supposed to make it click over to "loaded" isn't happening
slight delays like putting in alert() calls tend to make it start working
Any hints at all about even how to investigate this welcome.
This usually happens for me when I am running the page under a different domain from what has been registered in Facebook. Typically this is when I am developing locally.
If you are running locally, you'll have to set up a local web server and then modify your hosts file to point the the registered domain to 127.0.0.1 in order to test on your local machine. Don forget to remove that line from the hosts file when you want to test it on the server.
According to:
https://developers.facebook.com/bugs/240058389381072
You cannot put your application under sandbox mode, or else it won't work. Go into your app settings, advanced, and switch it. This stumped me for a couple hours until I happened upon the bug report.
I had similar problem with FB API. It turned out, that my Facebook App was misconfigured. Please make sure that this is not the case for you. My problem was that my "Site URL" param in FB application was pointing to https, but I was using http protocol for development. Any call against FB api after FB.init was not calling my callback functions. So the first thing to do should be to double check App config.
Now, if some reason you depend on FB api but you wish to have a fallback option in case it;s inoperative - workaround with timer should be ok for you. Just set up a timer and disable it if FB Api gives you proper response. If not - fallback to some custom function which will perform some additional logic.
function callFbApi() {
var timeoutHandler = setTimeout(function() { requestFailed(); }, 1000);
function requestFailed() {
// When this happens, it means that FB API was unresponsive
doSomeFallbackWork();
alert('hey, FB API does not work!');
}
FB.getLoginStatus(function(response) {
clearTimeout(timeoutHandler); // This will clear the timeout in case of proper FB call
doSomeUsualWorkAfterFbReplies();
return false;
}, true);
}
If your application is in sandbox mode, Facebook acts as if your application is invisible to anyone who is not listed as an application developer. If you're not logged in, then it would stand to reason that your app is now invisible.
The callback will only fire if you're initializing with a visible application. Otherwise the following response is returned:
<span>Application Error: There was a problem getting data for the application you requested. The application may not be valid, or there may be a temporary glitch. Please try again later. </span>
For more info please see my comment on this bug ticket:
https://developers.facebook.com/bugs/240058389381072
Maybe you are using the asynchronous call. The same thing happened when I called FB.init with window.fbAsyncInit. All I did was delay the FB.getLoginStatus with a setTimeout function
window.setTimeout(checkLogStatus, 1000);
function checkLogStatus(){
alert("check");
// fetch the status on load
FB.getLoginStatus(handleSessionResponse);
}
It seemed to work after that
On the new version of the Developer app, you have to make sure to have put the correct URL you are using to access the application in the Website field under the
Select how your app integrates with Facebook
section.
Make sure the protocol is HTTPS and not HTTP.
I had a similar problem. The site worked every time when I was opening the browser, but fails when I tried to reload.
The cause was the missing "www" on the site name on Facebook configurations. Note that putting "www" (like www.yoursite.com) works on both situations (yoursite.com or www.yoursite.com).
As others have posted, you must be accessing your site at the same URL that facebook expects. For example if facebook has a callback "example.com" but you're browser has "www.example.com", that can cause this problem.
In addition, if third-party cookies are not allowed by your browser, you may also see this problem. Or you may see the callback erroneously reporting the user is not connected.
Just posting a situation I had were calling FB.getLoginStatus got absolutely no response.
My application is designed to run in a tab, and I only entered the Page Tab URLs on the app admin page, and not the App On Facebook (i.e. Canvas) URLs. The tab loads perfectly, but any calls to the FB JS SDK provoke no response.
In Facebook App Settings, go to Client OAuth Settings, look at Valid OAuth redirect URIs
Make sure you have listed all URIs which are the domains from which Facebook SDK is being invoked. For example:
I develop at localhost:5000 and deploy to Heroku. Notice the format: http://domain.name/