Publish to a page wall using javascript API with a specific user - javascript

I'm trying to build a custom post to publish to one of my app facebookpage. I saw in the facebook documentation, the "from" is just a readonly property? theres a way to doit?.
var request = {
message: 'test 1234',
access_token: ACCESS_TOKEN,
from: {
id: MY_APP_ID,
category: "Other",
name: "My great app"
}
};
FB.api('/' + UserPageId + '/feed', post, request);
But instead of the post come from my app, is comming from the "UID" that owns that page.

You have to retrieve an access token as your app. Follow the instructions on the facebook authentication documentation under the section App Login and you will retrieve the correct access token - use that token when making the calls to the api and any action will be executed on behalf of the app.
This is the url to query for an app access token.
https://graph.facebook.com/oauth/access_token?
client_id=YOUR_APP_ID&client_secret=YOUR_APP_SECRET&
grant_type=client_credentials
If you are wanting to publish stories on behalf of a PAGE the process is a little different (its also detailed in the link above). You have to grant the manage_pages permission :
https://www.facebook.com/dialog/oauth?
client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&scope=manage_pages&
response_type=token
And then you can see a list of all the pages the user manages by querying this url :
https://graph.facebook.com/me/accounts?access_token=TOKEN_FROM_ABOVE
It'll give you a list of page names, page ids and page access tokens. Use those tokens to make calls to the graph api on behalf of a page.

Related

Facebook API - POST a comment on a private groups post

I have successfully retrieved an post made on an private group and the comments made on this post. I want also to make the users on my app to be able to reply to comments on that post but cant get my head around this problem.
This is the API URL to GET all the comments on an post ID.
1338804626636796_1351943298656262/comments
When i try to do a POST call to this URL i get as a result:
{ "error": {
"message": "(#3) Publishing comments through the API is only available for page access tokens",
"type": "OAuthException",
"code": 3,
"fbtrace_id": "AM6a-he8gLoFA8SDVHjfDYO"
}
}
As far as i understand Page Access Token is used to manage Pages... Im working with Groups not Pages, and when i try to create a Page Access Token my Group that i want to manage wont show up ofcourse.
I then follow this guide:
Get a page Access Token API Docs
It asks for a PAGE ID, i have group ID but i try it anyways and get this as a response:
code: 100 fbtrace_id: "AnzTkEAsbp8s-Z__QawDBYX" message: "(#100) Tried accessing nonexisting field (access_token) on node type (Group)" type: "OAuthException"

auth0 access token doesn't show issuer details

We recently added auth0 for integrating SSO from different oauth2 providers (e.g. contoso1.auth.com and contoso2.auth.com)
https://auth0.com/docs/quickstart/spa/angular/01-login
I followed the above link and Our front end app successfully integrated this in the code and able to signin and get the token.
{
"iss": "https://TENANT_NAME.auth0.com/",
"sub": "auth0|SOME_HASH",
"aud": [
"https://API_IDENTIFIER",
"https://TENANT_NAME.auth0.com/userinfo"
],
"iat": 1563699940,
"exp": 1563786340,
"azp": "SOME_OTHER_HASH",
"scope": "openid profile email"
}
In our angular app we want to render ui (show or hide links based on which authentication(contoso1/contoso2) user has gone through. But auth0 accesstoken doesn't give any details about the issuer "iss" (e.g.contoso1.auth.com or contoso2.auth.com)
We cannot rely on the email to say which SSO user belongs to as in our case contoso1 and contoso2 can have users from each others system with their own email ids.
After spending sometime on auth0 page i realized we have a field "connection" in the datacontext of auth0 object and it stores the name . While we can use this as a temporary workaround we can't rely on this determine which SSO flow user signed in with.
{
tenant: "identity-dev"
clientID: "fdsfsdf-dfsdfsd8989",
clientName: "Angualr Portal",
clientMetadata: "{}"
connection : "contoso1-backchannel",
connectionStrategy:"oidc"
....more
}
Please let me know how we can fetch iss or issuer url details in the token.
Is it a requirement to get this info using the frontend only?
As per this Auth0 article, it is a bit easier if you have a backend in place:
If your code runs in the backend, then we can assume that your server is trusted to safely store secrets (as you will see, we use a secret in the backend scenario).
With the backend you will be able to retrieve and parse the identities array user.identities[i].provider, which clearly identifies the original issuer under provider and connection keys.
If using only a frontend, it is more work and you need to build a proxy:
When working with a frontend app, the process for calling IdP APIs differs from the backend process because frontend apps are public applications that cannot hold credentials securely. Because SPA code can be viewed and altered, and native/mobile apps can be decompiled and inspected, they cannot be trusted to hold sensitive information like secret keys or passwords.
The quoted article contains links in the "Show me how" box that might be of further interest in this regard.
From your post it seems to be that only a frontend is used, but I included info about the backend in case it is worth your while to implement a small backend, if purely to just make retrieving the identity provider a bit easier.

Single flow: sign user in via Google oAuth AND grant offline/server access?

I'm trying to implement Google sign-in and API access for a web app with a Node.js back end. Google's docs provide two options using a combo of platform.js client-side and google-auth-library server-side:
Google Sign-In with back-end auth, via which users can log into my app using their Google account. (auth2.signIn() on the client and verifyIdToken() on the server.)
Google Sign-in for server-side apps, via which I can authorize the server to connect to Google directly on behalf of my users. (auth2.grantOfflineAccess() on the client, which returns a code I can pass to getToken() on the server.)
I need both: I want to authenticate users via Google sign-in; and, I want to set up server auth so it can also work on behalf of the user.
I can't figure out how to do this with a single authentication flow. The closest I can get is to do the two in sequence: authenticate the user first with signIn(), and then (as needed), do a second pass via grantOfflineAccess(). This is problematic:
The user now has to go through two authentications back to back, which is awkward and makes it look like there's something broken with my app.
In order to avoid running afoul of popup blockers, I can't give them those two flows on top of each other; I have to do the first authentication, then supply a button to start the second authentication. This is super-awkward because now I have to explain why the first one wasn't enough.
Ideally there's some variant of signIn() that adds the offline access into the initial authentication flow and returns the code along with the usual tokens, but I'm not seeing anything. Help?
(Edit: Some advice I received elsewhere is to implement only flow #2, then use a secure cookie store some sort of user identifier that I check against the user account with each request. I can see that this would work functionally, but it basically means I'm rolling my own login system, which would seem to increase the chance I introduce bugs in a critical system.)
To add an API to an existing Google Sign-In integration the best option is to implement incremental authorization. For this, you need to use both google-auth-library and googleapis, so that users can have this workflow:
Authenticate with Google Sign-In.
Authorize your application to use their information to integrate it with a Google API. For instance, Google Calendar. 
For this, your client-side JavaScript for authentication might require some changes to request
offline access:
$('#signinButton').click(function() {
auth2.grantOfflineAccess().then(signInCallback);
});
In the response, you will have a JSON object with an authorization code:
{"code":"4/yU4cQZTMnnMtetyFcIWNItG32eKxxxgXXX-Z4yyJJJo.4qHskT-UtugceFc0ZRONyF4z7U4UmAI"}
After this, you can use the one-time code to exchange it for an access token and refresh token.
Here are some workflow details:
The code is your one-time code that your server can exchange for its own access token and refresh token. You can only obtain a refresh token after the user has been presented an authorization dialog requesting offline access. If you've specified the select-account prompt in the OfflineAccessOptions [...], you must store the refresh token that you retrieve for later use because subsequent exchanges will return null for the refresh token
Therefore, you should use google-auth-library to complete this workflow in the back-end. For this,
you'll use the authentication code to get a refresh token. However, as this is an offline workflow,
you also need to verify the integrity of the provided code as the documentation explains:
If you use Google Sign-In with an app or site that communicates with a backend server, you might need to identify the currently signed-in user on the server. To do so securely, after a user successfully signs in, send the user's ID token to your server using HTTPS. Then, on the server, verify the integrity of the ID token and use the user information contained in the token
The final function to get the refresh token that you should persist in your database might look like
this:
const { OAuth2Client } = require('google-auth-library');
/**
* Create a new OAuth2Client, and go through the OAuth2 content
* workflow. Return the refresh token.
*/
function getRefreshToken(code, scope) {
return new Promise((resolve, reject) => {
// Create an oAuth client to authorize the API call. Secrets should be
// downloaded from the Google Developers Console.
const oAuth2Client = new OAuth2Client(
YOUR_CLIENT_ID,
YOUR_CLIENT_SECRET,
YOUR_REDIRECT_URL
);
// Generate the url that will be used for the consent dialog.
await oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope,
});
// Verify the integrity of the idToken through the authentication
// code and use the user information contained in the token
const { tokens } = await client.getToken(code);
const ticket = await client.verifyIdToken({
idToken: tokens.id_token!,
audience: keys.web.client_secret,
});
idInfo = ticket.getPayload();
return tokens.refresh_token;
})
}
At this point, we've refactored the authentication workflow to support Google APIs. However, you haven't asked the user to authorize it yet. Since you also need to grant offline access, you should request additional permissions through your client-side application. Keep in mind that you already need an active session.
const googleOauth = gapi.auth2.getAuthInstance();
const newScope = "https://www.googleapis.com/auth/calendar"
googleOauth = auth2.currentUser.get();
googleOauth.grantOfflineAccess({ scope: newScope }).then(
function(success){
console.log(JSON.stringify({ message: "success", value: success }));
},
function(fail){
alert(JSON.stringify({message: "fail", value: fail}));
});
You're done with the front-end changes and you're only missing one step. To create a Google API's client in the back-end with the googleapis library, you need to use the refresh token from the previous step.
For a complete workflow with a Node.js back-end, you might find my gist helpful.
While authentication (sign in), you need to add "offline" access type (by default online) , so you will get a refresh token which you can use to get access token later without further user consent/authentication. You don't need to grant offline later, but only during signing in by adding the offline access_type. I don't know about platform.js but used "passport" npm module . I have also used "googleapis" npm module/library, this is official by Google.
https://developers.google.com/identity/protocols/oauth2/web-server
https://github.com/googleapis/google-api-nodejs-client
Check this:
https://github.com/googleapis/google-api-nodejs-client#generating-an-authentication-url
EDIT: You have a server side & you need to work on behalf of the user. You also want to use Google for signing in. You just need #2 Google Sign-in for server-side apps , why are you considering both #1 & #2 options.
I can think of #2 as the proper way based on your requirements. If you just want to signin, use basic scope such as email & profile (openid connect) to identify the user. And if you want user delegated permission (such as you want to automatically create an event in users calendar), just add the offline access_type during sign in. You can use only signing in for registered users & offline_access for new users.
Above is a single authentication flow.

How to use App Access Token to update Open Graph Tags

I want to dynamically update Open Graphs Tags on my website, but don't know how to do it properly.
I have understood you're not supposed to use the access token in a client side script, but how do I go about and update it otherwise.
I have seen examples online that does not use an access token, but I get an authorization error then.
Can I make any settings on facebook developer to skip access token or how can I make a call from my javascript, without showing the access token or app secret?
This is the part of my script which runs after modifying the meta:og tags:
//Update Open Graph
$.post(
'https://graph.facebook.com',
{
access_token: '123',
id: strCurrentUrl,
scrape: true
},
function(response){
console.log(response);
}
From Facebook:
for security, app access token should never be hard-coded into
client-side code, doing so would give everyone who loaded your webpage
or decompiled your app full access to your app secret, and therefore
the ability to modify your app. This implies that most of the time,
you will be using app access tokens only in server to server calls.

How do I get the logged in users profile for Azure AD OAuth logins?

Following on from JavaScript OAuth2 flow for Azure AD v2 login does not give an access_token, I'm trying to figure out the best endpoint to use, to get the logged in users details (eg, display name, email, etc.).
However, I noticed in there are 2 potential endpoints I can use
https://outlook.office.com/api/v2.0/me
https://graph.microsoft.com/v1.0/me
1, is used in bell for hapijs and is documented in Use the Outlook REST API. However, in bell, I can't seem to figure out the scope I need to get it working for OAuth 2.0. I've tried openid, email, profile, Mail.Read (only trying this because I've seen it in some docs), and User.Read, but the first 3 scopes don't give back a access_token as per JavaScript OAuth2 flow for Azure AD v2 login does not give an access_token, and the last 2 (Mail.Read, and User.Read) give me an access_token, but they give me authentication issues when calling https://outlook.office.com/api/v2.0/me with Authorization: 'Bearer [access_token].
I found the endpoint for 2 at Microsoft Graph: Get user and it seems to work with the User.Read scope. I get the following response using the access_token returned:
{
'#odata.context': 'https://graph.microsoft.com/v1.0/$metadata#users/$entity',
id: '60...',
userPrincipalName: 'some#email.com',
businessPhones: [],
displayName: null,
jobTitle: null,
mail: null,
mobilePhone: null,
officeLocation: null,
preferredLanguage: null
}
The problem with the response here is that there isn't an explicit email field, but I guess I can just use userPrincipalName (the userPrincipalName is also used for the bell Azure AD provider)
So my question is which endpoint am I supposed to use? Or is there another one somewhere else?
You should absolutely use Microsoft Graph for this and the /v1.0/me endpoint is the correct URI for retrieving the user's profile information.
As for finding their email address, there are a few potential properties you could pull:
mail: This is the default SMTP address for the user. If it is showing up as null, this suggests the value wasn't populated. Normally this is populated automatically by Exchange but depending on the tenant it may need to be manually populated.
proxyAddresses: This is an array of addresses associated with the user. Typically you only use this property when you need to surface a user's alternative email aliases (i.e. name#comp.com & firstname.lastname#comp.com).
If you are only looking for very basic information (name and email) you be able to use OpenID Connect and skip the Microsoft Graph call entirely. OpenID Connect supports returning the user's profile as part of the profile.
To use OpenID Connect you need to make a couple of changes to your Authorization request (i.e. the initial call to https://login.microsoftonline.com/common/oauth2/v2.0/authorize):
The response_type must include id_token. (eg. &response_type=id_token+code)
The scope must include openid, profile, and email (eg. &scope=openid profile email user.read).
When enabled, you will receive an additional property in your Access Token response named id_token. This property holds a JSON Web Token (JWT) that you can decode an obtain the user's profile information:
As an illustration, I used the settings above to request a token from my test Azure AD instance. I took that token and decoded it (I used http://jwt.ms/ but JWT decoder would work) to get the OpenID Connect profile:
{
"typ": "JWT",
"alg": "RS256",
"kid": "{masked}"
}.{
"aud": "{masked}",
"iss": "https://login.microsoftonline.com/{masked}/v2.0",
"iat": 1521825998,
"nbf": 1521825998,
"exp": 1521829898,
"name": "Marc LaFleur",
"nonce": "a3f6250a-713f-4098-98c4-8586b0ec084d",
"oid": "f3cf77fe-17b6-4bb6-8055-6aa084df7d66",
"preferred_username": "marc#officedev.ninja",
"sub": "{masked}",
"tid": "{masked}",
"uti": "{masked}",
"ver": "2.0"
}.[Signature]
The ID Token and Access Token can return attributes like display name, email, etc.
Sample ID Token.
See "Select Application claims" here: Azure Active Directory B2C: Built-in policies
Select Application claims. Choose claims you want returned in the authorization tokens sent back to your application after a successful sign-up or sign-in experience. For example, select Display Name, Identity Provider, Postal Code, User is new and User's Object ID.

Categories

Resources