How get Facebook token using Oauth2 with chrome.identity - javascript

I'm using chrome.identity in a packaged app to get a user token using Facebook. I call chrome.identity.launchWebAuthFlow, and I need to take the access token, send it to the server, and then access token is used to verify the user.
Works great with Google+. But for some reason, it doesn't work for Facebook. For some reason, Facebook's OAuth appears to be special. I've added the extensionid.chromiumapp.org to the list of redirect URLs in the API. Added
"https://extensionid.chromiumapp.org/*",
"https://facebook.com/*",
"https://www.facebook.com/dialog/",
"https://graph.facebook.com/*"
to manifest.json. But nothing changed.
In calling chrome.identity.launchWebAuthFlow I use URL like this
"https://www.facebook.com/dialog/oauth/access_token?" +
"client_id=myclientid&client_secret=myclientsecret&" +
"response_type=token&grant_type=client_credentials"
When I try to invoke it, I get the following error message:
«launchWebAuthFlow completed Object {message: "Authorization page could not be loaded."} »
And when I use URL like
«"https://www.facebook.com/dialog/oauth?client_id=myclientid&redirect_uri=https://myextensionid.chromiumapp.org/facebook.com=token&scope=user"»
I get the next error:
«launchWebAuthFlow completed Object {message: "User interaction required."} undefined »
I try to get facebook token in 4 days. I am tired. What I do wrong?
Why chrome.identity.getAuthToken work great for Google+ and chrome.identity.launchWebAuthFlow dont with Facebook?
I hope someone have done the same things and can help me.

I have solved the problem. Here is an example https://github.com/blackgirl/Facebook_Oauth2_sample_for_extensions

The "User interaction required." message means that the user needs to sign in to Facebook, and/or approve the requested OAuth scopes. The setting the { interactive: true } flag would allow identity.launchWebAuthFlow to display a window where the user would perform these steps. Since you are passing the { interactive: false } flag, identity.lauchWebAuthFlow fails.
https://www.facebook.com/dialog/oauth is most likely the URL you want to use to start your flow. The client_credentials grants are normally for cases where you are accessing resources owned by your app, rather than resources owned by a specific user.
However if you did want to debug that "Authorization page could not be loaded" case, the way to do it would be to open up chrome://net-internals and look for error responses coming back from Facebook.

chrome.identity.launchWebAuthFlow(
{'url': 'https://www.facebook.com/dialog/oauth?client_id=myclientid&redirect_uri=https://myextensionid.chromiumapp.org/facebook.com=token&scope=user, 'interactive': true},
function(redirect_url) {
/* Extract token from redirect_url */
console.log(redirect_url);
});
//'interactive': true
what will this flag do, will show a dialog box asking username and password
upon successful login it will ask for grant access just press that and
you will receive redirect url in above function body.

Related

Is it possible to post to chat.postMessage as any user in a Slack team?

I'm building a Slack integration that is intended to modify some text and then post it to a Slack channel as though the user who triggered the command had said it.
e.g. /makeFace disapproval
#Ben 3:45pm
ಠ_ಠ
I ask for the client permission scope, which adds the chat:write:user permission. But when I hit the chat.postMessage endpoint, it only seems to allow you to post as the user who added the integration because the token it returns seems to be individuated for that user.
I know that giphy, for instance, sends its gif messages as though you are the originator, but I can't find out how they manage it. Is there any documentation for sending messages as other members of the team?
There are 2 ways to achieve this:
A. Overwriting username and icon
When you send a message with chat.postMessage it is possible to set a user name with the property username. The message will then appear as being send by that user (same for icon with icon_url).
However, this is not meant to impersonate real users, so even if you use the same username and icon as the real user the message will have the app tag, so that they can be distinguished from a real user.
Here is an example how it looks like (from a gamer Slack about flying and killing space ships):
But depending on what your requirements are that might work for you.
If you want to use it make sure to also set the as_user property to false (yes, really) and it will not work with a bot token, only with a user token.
See here for more details on how it works.
This also works for the legacy version of Incoming Webhooks, not with the current version of incoming webhooks though. (You can still get the legacy version, see this answer)
B. Having the user's token
Another approach is to always use the token from the respective user for sending the message. In combination with as_user = true messages sent by your app will look exactly as if they would come from the respective user (no APP tag).
To make that happen your app would need to collect tokens from all users on your workspace and store them for later use. This can be done by asking every user to install your app (called adding a "configuration") through the Oauth process (same you use to install your app to a workspace), which allows your app to collect and store those tokens for later use.
Update: This doesn't work. It impersonates the user who installed the app, so it merely seems to work... until another user tries to use it (and they end up impersonating you).
Go to your App's management page. Select "OAuth & Permissions".
Add the chat.write OAuth Scope to your app as a User Token Scope, not a Bot Token scope.
Take note of your User OAuth Token at the top of this page (not your But User OAuth Token).
Call chat.postMessage with
username = user id of the user you'd like to post on behalf of
token = the token from step 3. above
The resulting post will be 100% impersonated. Not just the name and icon as mentioned in other answers, but it'll 100% function as if it came from the user.
I hope this will help those who are still facing this issue.
First give the chat:write and chat:write.customize scope to your bot. The scope chat:write.customize Send messages as #your_slack_app with a customized username and avatar
From "OAuth & Permissions" settings get the bot OAuth token or even bot access token (both will work).
Then set the arguments like the following.
username to specify the username for the published message.
icon_url to specify a URL to an image to use as the profile photo alongside the message.
icon_emoji to specify an emoji (using colon shortcodes, eg. :white_check_mark:) to use as the profile photo alongside the message.
You can visit the docs from here

Facebook login: Please make sure your redirect_uri is identical to the one you used in the OAuth dialog

So I'm out of ideas, I don't know what to check or debug anymore, but on the exception I get this:
string(188203) "Facebook\FacebookAuthorizationException Object
(
[statusCode:Facebook\FacebookRequestException:private] => 400
[rawResponse:Facebook\FacebookRequestException:private] => {"error":{"message":"Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request","type":"OAuthException","code":100,"fbtrace_id":"DqCCKoiN0r4"}}
[responseData:Facebook\FacebookRequestException:private] => Array
(
[error] => Array
(
[message] => Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request
[type] => OAuthException
[code] => 100
[fbtrace_id] => DqCCKoiN0r4
)
)
[message:protected] => Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request
[string:Exception:private] =>
[code:protected] => 100
You can set redirect URI in
Go to https://developers.facebook.com/apps
Select your app.
Under Products > Facebook Login > Settings
Enable Embedded Browser OAuth Login
Set Valid OAuth Redirect URIs
You can Validate Redirect URI with Redirect URI Validator.
You can only use https URIs.
Also set App Domain in Settings > Basic > App Domains
Try / at the end of redirect URI
In my case I was using https://localhost everywhere but somehow when getting access token specifying https://localhost/ worked.
As absurd as it sounds, verify you're using the correct app_secret.
Facebook will give you this instead of just saying "invalid secret" in the response
I believed you have used different redirect_uri in your facebook app settings and Oauth API code. thats why you got this error.
For facebook login you must set same redirect_uri into both place.
Make sure to have it exactly as in your FB settings.
For me, I had https://localhost:3000/ in my settings but https://localhost:3000 in my get access token call and this was the source of the error!
I had the same issue and non of the answers helped me, then I tried to make another Facebook app, and it solved my issue!
I mean you have to use one application for Facebook OAuth and make another to use for Instagram oauth. seems Facebook has an issue with using both functionalities in one app.
After engaging in the problem for more than a day, found my mistake to be one '/' (slash) in app url at the end.
incase anyone else is having this issue and can't figure it out, your redirect_uri needs to have a "/" at the end. Facebook adds one automatically when you put your redirect_uri in the app settings. If you don't add the "/" in your code when you're trying to get the token, it will give you this error. That's what was going on with mine.
Ex: redirect_uri = "https://myserver.com:4429"
should be
redirect_uri = "https://myserver.com:4429/"
It means the redirect URI you pass to FB (usually in the query string) does not match what you have set in the app settings.
It can also be because of multiple slashes, for ex:
https://yoursite.com/auth/facebook/callback -> that's the one you added in the app settings
https://yoursite.com//auth/facebook/callback -> that's what you actually send
For me, it worked by replacing
callbackURL: "api/auth/facebook/redirect/",
to
callbackURL: "http://localhost:3000/api/auth/facebook/redirect/",
in the new FacebookStrategy
Was stuck in the same problem for a long time .
You will get this error when the redirect url is mismatching or does not exist or is wrongly formatted in the field (additional spaces or // ) , either the facebook app setting or while you are calling the API .
Solution
What worked for me was when ever you add a redirect URl you can check it in the valid redirect auth field uf it doesnot show valid when pressed check than that url is not the correct one
I finally managed to get this to work, in my case, I was using the Instagram Oauth API but I believe the logic is the same and you can find the complete flow here : https://developers.facebook.com/docs/instagram-basic-display-api/guides/getting-access-tokens-and-permissions.
So here is the basic flow :
Generate an authorization which will provide you with a code (the user will get redirected to Instagram in order to accept/deny the requested authorizations)
This code can be used in order to generate a 'short lived access token' and this is where the troubles arise.
For the first point, you need to provide Instagram with a redirect_uri. When you want to complete the second point, you'll need to make a POST request to Instagram, with a redirect_uri as well.
I thought that both redirect_uri's could be different between the 2 steps, but they don't. And this is simply where my error was : I wanted something like that for the first step : https://my.domain/short-lived-token and something like this for the 2nd : https://my.domain/short-lived-token but when I tried both with https://my.domain/generate-access-token, for instance, it worked.
Hope it helps you guys because I couldn't find anything on the internet.
LATEST FIX:
After sending 3 hours, I found a solution to this error.
This happened due to 2 reasons.
As we can see in response. Just Make sure you set the same URL in the developer portal and code
IMP: FACEBOOK needs to change the API response. 2nd reason is that you make sure that using Instagram App Secret and app ID. I was getting the same error bcoz I was using the wrong app secret.
Must Follow: Official FB Docs

Meteor.user is null after (apparently) successful login

I have a simple Meteor js app that allows you to create a user account and log in, or to log in with your existing Google account via oauth (thanks to the accounts-google package).
When using the app, I enter my username and password, everything works fine. However, when I click "Sign in with Google", the google oauth pop-up asks me to select which google account I want to use for this login. I select the account, the pop up waits a second, closes, and then nothing happens. No pop-ups being blocked, no "failed login" messages. It's as if nothing happened at all.
I'm certain that the user is never being defined when I use oauth login because Meteor.user() gives me null in the JS console.
What could be going on here? Or how would I debug this? Suggestions appreciated.
p.s. If any additional information is needed, I can ammend.
You probably messed up oauth configuration either on the Meteor side or Google Developers Console side, so here is a quick recap.
Google Developers Console :
Under APIs & auth > Credentials, create a new Client ID in the OAuth section.
Choose Web Application and specify both correct redirect URIs and JavaScript origins :
REDIRECT URIS
http://localhost:3000/_oauth/google?close
http://your-production-domain.com/_oauth/google?close
JAVASCRIPT ORIGINS
http://localhost:3000
http://your-production-domain.com
Meteor configuration :
Be sure to add these packages :
meteor add accounts-google
meteor add service-configuration
In server/config.js, add these lines from http://docs.meteor.com/#meteor_loginwithexternalservice
ServiceConfiguration.configurations.remove({
service: "google"
});
ServiceConfiguration.configurations.insert({
service: "google",
clientId: "????????????????.apps.googleusercontent.com",
secret: "????????????????"
});
The clientId and secret fields should be set to those in the Google Developers Console.
Then call Meteor.loginWithGoogle() in the click handler of your login form and it should work as expected.

Can't login to Instagram using Client-Side (Implicit) Authentication

I'm trying to build a client-side application that allows people to login with their Instagram accounts. Problem is, I'm not sure if that's still possible.
I've coded a sample JavaScript after reading "Client-Side (Implicit) Authentication" section of their related docs.
I'm getting the following error:
{
"code": 400,
"error_type": "OAuthException",
"error_message": "JS login temporarily disabled"
}
From the error message I'm guessing it's not about my code but it's something on Instagram's side. Is there a way for me to do client-side login? Also, if I can't, what are my options?
Thanks.
I had similar issue and this is how I fixed it.
You have to uncheck the "Disable implicit OAuth:" by going to :
-> Manage Clients
-> Click edit on the app/webapp.
-> Uncheck - Disable implicit OAuth:
-> Update the settings and try to run it again by going to the link :
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=token
In the link, replace the values that were provided to you and in the response_type, give value as token to get the access token and if you want to get the request code, just replace token with the code in the URL.
Hope this helps for you and for future viewers.. Good luck.. :)
Just unset the "Disable implicit OAuth:" in app settings.
So, it seems it's impossible to do JS login at the moment with Instagram.
But they still allow implicit redirects so the solution is to have a server to make a redirect to your client side application. You only need two endpoints. I've written a small Node.JS app for this which you can find here.
I had tried for the same,I think there are not still providing any api to login with Instagram credentials username and password,You can just authenticate your account via
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code

Google Javascript Client library OAUTH asks for Offline Access permission, though it was never requested

My application interacts with Google with Javascript only. It asks for user profile access, email access and contacts management permissions.
Upon loading a page, the application checks if the user has already granted those permissions and obtains an access token if he had.
Here is some sample code:
var GoogleContacts = {
...
checkAuth: function(){
gapi.auth.authorize({
client_id: googleKeys.clientId,
scope: googleKeys.scopes,
immediate: true
},
jQuery.proxy(this.handleAuthResult, this)
);
},
askAuth: function(){
gapi.auth.authorize({
client_id: googleKeys.clientId,
scope: googleKeys.scopes,
immediate: false
},
jQuery.proxy(this.handleAuthResult, this)
);
}
...
}
....
function handleGoogleApiLoad(){
gapi.client.setApiKey(googleKeys.apiKey);
gapi.auth.init(function(){console.info('popup api ready')});
setTimeout(function(){GoogleContacts.checkAuth();}, 300);
}
....
$('#emailButton').click(function() {
if(!accessToken)
GoogleContacts.askAuth();
...
});
Now, if user comes for the first time, he is asked the correct permissions when he pressed the "Send email" button. When user reloads a page, the seamless permissions check returns failure and when user hits a "send email" button, we open the Google authorization popup again, and it now asks for Offline Access permission.
This seems incorrect as the JS api has no actual use for offline access.
Looks like this problem started after Google released the incremental auth feature: http://googleplusplatform.blogspot.co.il/2013/12/google-sign-in-improvements11.html
Is this a bug that will soon be fixed, or should we change the code somehow to not confuse our users with weird permission requests?
Update:
I have tried to use the plus api and gapi.auth.signIn() method but with the same result.
Apparently, this problem is scope-dependant, as when I use only the login scope, everything works as expected, but adding the Google Contacts access scope https:||www.google.com/m8/feeds/ always leads to the Offline Access request when entering page second time. Here is a fiddle to confirm this: http://jsfiddle.net/hjLM6/6/
This must be a bug and I really would like Google to deal with it soon, as it scares users away.
The immediate:false parameter in your askAuth method is the cause. The post that Abraham mentions explains the background.
The gapi.auth.authorize() method should generally be avoided in most cases now that the gapi.auth.signIn() method is available to handle programatic initiation of the authorization flow and also you should make use of the dynamic callbacks. The information on monitoring a user's session state explains how and when to get your sign-in callback function to fire and how you can use the values within the auth result object to determine if they've previously authorized your app, signed in (or out) of your app, or signed in (or out) of google.
Your checkAuth and askAuth functions would effectively be combined to check the status of the auth result object and act accordingly. Your email button click event would trigger instead gapi.auth.signIn() with the necessary parameters and scopes for your app.
I just had exactly the same issue with drive.readonly scope, for what it's worth the way I worked around it is by always calling authorize with immediate = false. This isn't that bad because when you do this for an already authorized user, Google will open the popup for a fraction of a second but then will immediately close it (apparently making use of the chance to open the popup in the browser event handler in case the user does need to authorize).
Curiously, for localhost server where I previously used immediate = true, I continue to see requests for offline access - but on the production server I haven't seen seen them so far, fingers crossed.

Categories

Resources