I want to greet the user with his name when he access my app for a second time. For this I have already implemented account linking and now I want to get his displayName and for what I have read I need to ask for his permission to access such information, so I did as it is on the following piece of code:
welcome(app){
let welcomePhrase = "";
console.log('UserId: ' + app.getUser().userId);
if (app.isPermissionGranted()) {
console.log('--------------- Permission granted ---------------');
const displayName = app.getUserName().displayName;
welcomePhrase = "Welcome back $1!".replace("$1",displayName);
}
else{
console.log('--------------- Permission denied ---------------');
this.requestPermission(app);
welcomePhrase = "Welcome";
}
app.ask(welcomePhrase);
}
requestPermission (app) {
app.askForPermission('Can I keep one information from you?', app.SupportedPermissions.NAME);
}
The welcome method is called from my Default welcome intent and I do can see the app asking for the permission:
(yeah, it is in PT-BR)
What I'm not getting is what should I as a user answer, as replying "sim"(yes), "sim, vocĂȘ pode" (yes you can) or anything similar keeps being answered by my default fallback.
The main idea is that you have to request the permission, Google asks the user for you, you received the answer back by catching the event coming back to Dialogflow.
Wassim Chegham wrote a good article: https://medium.com/google-developer-experts/handling-permissions-with-dialogflow-and-actions-on-google-b08c8f228c00
More documentation here:
https://developers.google.com/actions/assistant/helpers
Related
I'm using Sails with Passport for authentication. I'm using passport-google-oauth(OAuth2Strategy) and passport-facebook for enabling Google Sign-in.
I'm not too well-versed with Passport, so pardon me if this is a rookie question. I've set up login via Facebook and it works just fine. With Google, I do receive an authorization code after allowing access to the app, but the I'm eventually not authenticated. I'm guessing the same code should work for both Facebook and Google since the strategies are both based on oauth2.
I'm not even sure what code to share, since I'm using the auto-generated code from sails-generate-auth, but do let me know if there's anything else I can share.
Any ideas on why this might be happening? The app is locally hosted but that's unlikely to be the problem since I am getting to the authorization stage anyway.
I faced the same problem and it was located here in in api/services/passport.js:
// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
user.username = profile.username;
}
// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
return next(new Error('Neither a username nor email was available'));
}
The Google service was not returning a profile.username property.
Because of it, the user is not saved in the database and cannot be authenticated. Then the passport callback receives an empty user, so the function that handles errors is fired and the user is redirected to the login page.
This change allows to use the displayName property as the username:
// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
user.username = profile.username;
}
/** Content not generated BEGIN */
// If the username property was empty and the profile object
// contains a property "displayName", add it to the user.
if (!user.username && profile.hasOwnProperty('displayName')) {
console.log(profile); // <= Use it to check the content given by Google about the user
user.username = profile.displayName;
}
/** Content not generated END */
// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
return next(new Error('Neither a username nor email was available'));
}
You could also use the profile.id property because profile.displayName is not necessarily unique (ie: two Google accounts can have an identical displayName). But it is also true accross different services: a Twitter account could also have the same username than a Facebook account. If both register on your application, you will have a bug. This is a problem from the code generated by sails-generate-auth and you should adapt it with the behavior that you want.
I will propose a PR if this solution works for you too.
Alright, so this ultimately turned out to be a known issue with the API.
TL;DR: Enable the Google+ API and the Contacts API as mentioned here. (The Contacts API isn't required, as #AlexisN-o pointed out in the comments. My setup worked as desired with Contacts API disabled. This obviously depends on what scope you're using.)
I believe it's not a nice way of failing since this was an API error that was prevented from bubbling up. Anyway, I dug into passport.authenticate to figure out what was going wrong. This eventually calls the authenticate method defined in the package corresponding to the strategy (oauth2 in this case). In here (passport-google-oauth/lib/passport-google-oauth/oauth2.js) I found that the accessToken was indeed being fetched from Google, so things should be working. This indicated that there was a problem with the requests being made to the token urls. So I ventured a little further into passport-oauth2/lib/strategy.js and finally managed to log this error:
{ [InternalOAuthError: failed to fetch user profile]
name: 'InternalOAuthError',
message: 'failed to fetch user profile',
oauthError:
{ statusCode: 403,
data: '{
"error": {
"errors": [{
"domain": "usageLimits",
"reason": "accessNotConfigured",
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration.",
"extendedHelp": "https://console.developers.google.com"
}],
"code": 403,
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration."
}
}'
} }
This was the end of the hunt for me and the first result for the error search led to the correct answer. Weird fix though.
I am using the OAuthWebSecurity with MVC to allow users of my website to login using Facebook's oAuth. Everything works fine, and I have a test user authenticating fine.
My question is based on the details Facebook can provide. I am currently returning the user details using the following...
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication();
This will give the follwing details:
UserName (email)
ProviderUserId
I also get a ExternalData object which has:
UserName
Name
Gender
Do you know if it's possible to get further data, maybe DoB, photo etc?
Pardon me for not framing me the full answer. I am just supplying a link. Please check
http://blue-and-orange.net/articles/facebook/displaying-facebook-user-data-in-aspnet-mvc-4/
Everything is explained here.
For setting permission you can go through this documentation
https://developers.facebook.com/docs/facebook-login/permissions/
if you were to request a user's email address, but never asked them for the 'email' permission, you would receive an OAuth error as show below.
try {
var client = new FacebookClient("my_access_token");
dynamic result = client.Get("me/email");
var email = (string)result.email;
}
catch (FacebookOAuthException) {
// The access token expired or the user
// has not granted your app 'email' permission.
// Handle this by redirecting the user to the
// Facebook authenticate and ask for email permission.
}
I think this is because Facebook just made some changes to their login process.
A few days ago, my air app was working with the FacebookDesktop class from the facebook-actionscript-api. Today I opened the project, and noticed that the Facebook login screens are a little different than when I started building my app. After I type my userID and password in, I grant the app access to my public profile, friend list and photos. Then another screen comes up where I grant the app permission to post to my friends on my behalf.
Then the window closes, and I get 'OAuthException 2500 An active access token must be used to query information about the current user.'
When I sign into Facebook through a browser, I see that my app shows up under "Your Apps" but I can't log in and do anything through my app.
I'm using Adobe Flash with GraphAPI_Desktop_1_8_1.swc on OSX Lion.
Here is my code:
public function MyApp(){
FacebookDesktop.init(APP_ID, onInit);
}
protected function onInit(result:Object, fail:Object):void {
if (result) {
trace("onInit, Logged In\n");
} else {
trace("onInit, Not Logged In\n");
var permissions:Array = ["publish_stream", "user_photos"];
FacebookDesktop.login(onLogin, permissions);
}
}
protected function onLogin(result:Object, fail:Object):void {
if (result) {
trace("Logged In as:");
trace(FacebookDesktop.getSession().user.name);
} else {
trace("Login Failed");
trace('code: '+fail.error.code); //code: 2500
trace('message: '+fail.error.message); //message: An active access token must be used to query information about the current user.
trace('type: '+fail.error.type); //type: OAuthException
}
}
I get the same results when I use the FlashDesktopExample provided in the SDK (modified with my app ID of course).
Any help would be great! Thanks in advance!
I ran into this problem, too: the success URL did not have any parameters.
Cadderly82 is correct; it's a problem with secure navigation. Turning off my Facebook account's "Secure Browsing" option fixed the problem, but I didn't want to have to require users to do that.
I was able to solve this by setting ALL of the FacebookURLDefaults values to use "https://".
Now I get a valid user-access-token in the success URL; and I get valid values regardless of my facebook account's secure-browsing setting.
I have figured out the problem:
The LoginWindow class sets the token based on the uri.
This worked fine until the LOGIN_SUCCESS_URL (http://www.facebook.com/connect/login_success.html) and the LOGIN_SUCCESS_SECUREURL (https://www.facebook.com/connect/login_success.html) pages stopped including the access token in the uri.
Hence, the token is never set. Even though my app shows up under the 'Your Apps' section in Facebook after I login, my app still can't do anything without a token.
I have two solutions:
The easiest is to change the LOGIN_SUCCESS_URL and/or the LOGIN_SUCCESS_SECUREURL properties in com.facebook.graph.core.FacebookURLDefaults like the following.
beginning on line 82:
public static var LOGIN_SUCCESS_URL:String = 'http://www.facebook.com/connect/login_success.html';
public static var LOGIN_SUCCESS_SECUREURL:String = 'https://www.facebook.com/connect/login_success.html';
Change to:
public static var LOGIN_SUCCESS_URL:String = 'http://www.yourwebsite.com/';
public static var LOGIN_SUCCESS_SECUREURL:String = 'https://www.yoursecurewebsite.com/';
of course you would use your own website - not 'http://www.yourwebsite.com/'. I tried it using http://localhost/ and it worked great.
Another solution is:
Change com.facebook.graph.windows.LoginWindow with the following code. I have made some changes to my files, so please forgive me if the line numbers are different than what they are in a fresh copy of the SDK.
around line 143:
change:
vars.redirect_uri = FacebookURLDefaults.LOGIN_SUCCESS_URL;
to:
vars.redirect_uri = 'http://localhost/';
In production code, you probably want to use your own website address instead of localhost, but I used localhost for testing purposes.
Then, in the handleLocationChange function (should be around line 168) add this to the else if statements:
}else if (html.location.indexOf ('http://localhost/') == 0) {
loginCallback(getURLVariables(), null);
userClosedWindow = false;
html.stage.nativeWindow.close();
html.removeEventListener(Event.LOCATION_CHANGE, handleLocationChange);
}
As I said before, change localhost to your website address.
I hope this helps!
I was having the same problem for random users and I don't really know if it is a Facebook problem with secure navigation:
Check user properties in Facebook: Security Settings > Secure Browsing
(www.facebook.com/settings?tab=security)
For users with "disabled" state it works fine.
For users with "migration" state it gives the error.
For users with previously "enabled" state it works fine.
When I tried with users in "migration" state and changed to "disabled", it worked fine.
Then if I turned it "enabled", the "migration" state is gone and marked as "enabled", but the error it's still there.
So I guess this is the problem, but don't know how to fix it.
alot has change in a year this is what i think the answer is now
you need a token to login FacebookDesktop.getSession().accessToken
public function MyApp(){FacebookDesktop.init(APP_ID, onInit, FacebookDesktop.getSession().accessToken); }
I am using Zend and I have an email sent to all members which contains a link to a Post. Only members logged in can comment but all guest can see it. Of course whoever is clicking on the link in the email should be able to comment straight away.
For this reason what I would like to find out is a way to check if a member clicking on the link is logged in or not:-
if already logged in the URL in the email should take the member to the Post directly.
if not logged in forward the member to the log in page and then to the proper URL containined in the link.
I hope I explained myself. Please ask me if not. Could someone please advise the best way to do it?
Thank you. F.
Create a plugin and save the requested Uri in the session using:
$this->_session->lastUrl = $this->getRequest()->getRequestUri();
Then, after the user enters his credentials, redirect him to this saved URL.
Another option would be to save the url and add it as parameter to the next requests, like Google, Yahoo and SO do.
public function emailAction()
{
$loggedIn = Zend_Auth::getInstance()->getIdentity();
if($loggedIn)
{
$this->_helper->_forward('post);
}else {
$this->_helper->_forward('login');
}
}
public function loginAction()
{
$success = new Zend_Session_Namespace('success');
if(!isset($success->url))
{
$success->url = $this->view->serverUrl(true);
}
$form = new Login_Form();
if($this->getRequest()->isPost() && $form->isValid($_POST))
{
$this->_redirect($success->url);
}
}
I'm developing using the Facebook PHP SDK.
I wanted to make it so that when the user logs out of Facebook, they will automatically be logged out of my website too.
I am using the following code to detect the session, using the session cookie:
$facebook->getUser();
For some reason, the getUser() function still returns the user's Facebook ID, even after they have logged out of Facebook on their website.
Am I to detect the session first using another Function?
On the official documentation example here, is the following excerpt from their comments:
// Get User ID
$user = $facebook->getUser();
// We may or may not have this data based on whether the user is logged in.
//
// If we have a $user id here, it means we know the user is logged into
// Facebook, but we don't know if the access token is valid. An access
// token is invalid if the user logged out of Facebook.
This lead me to believe that the session cookie for Facebook would become unset upon Facebook logout?
Kind Regards,
Luke
I have the same issue!
The FB PHP SDK saves those things into the $_SESSION!
You can delete them like this when your user clicks logout:
$_SESSION['fb_'.APP_ID.'_user_id'] = '';
$_SESSION['fb_'.APP_ID.'_access_token'] = '';
Although this is not the final solution, it works for now.
I appreciate comments and solutions on that!
I want to give an alternative, in a way you don't have to handle session stuff. Although, I must warn you this is slower than cleaning up the session, because it relies on a new request. What we're doing in the code below is to check on Facebook if the token is still valid. Here it's:
try {
$facebook->api('/me','GET');
$logged = true;
} catch(FacebookApiException $e) {
$logged = false;
}
In my case, I was doing everything using the JavaScript SDK, so I couldn't clean session on logout. But in my landing page, I was needing a work around to check it before send the response back.
If you're facing something like this, definitely a good solution.
The problem seems to be in php-sdk in basefacebook.php at line 567
protected function getSignedRequestCookieName() {
return 'fbsr'.$this->getAppId();}
This method returns the name of the cookie the sdk is looking for. However, javascript-sdk uses 'fbs_' prefix. Change this to 'fbs_' and it works fine.
return 'fbs'.$this->getAppId();}
$facebook->destroySession();
To destroy the session you can also use:
$facebook->destroySession();