I'm just starting out with Facebook SSO and OpenGraph. I have SSO working with my iOS app and now I'm starting to see how to publish OpenGraph actions.
I've set up a new Action Type and I need to submit it. When I do, I get the error:
You must publish at least one action to your Timeline using this action type. Review the documentation.
Ok, so I click the helpful documentation link and it tells me I want to do this:
https://graph.facebook.com/me/recipebox:cook?recipe=http://www.example.com/pumpkinpie.html&access_token=YOUR_ACCESS_TOKEN
So I translate that into this:
https://graph.facebook.com/me/fotoferret:hug?ferret=http://www.example.com/pumpkinpie.html&access_token=MY_ACCESS_TOKEN
fotoferret is my namespace, hug is my action
where MY_ACCESS_TOKEN is the value returned by:
https://graph.facebook.com/oauth/access_token?grant_type=client_credentials&client_id=MY_APP_ID&client_secret=MY_APP_SECRET
When I pasted my translated URL I get this error back:
{
"error": {
"message": "An active access token must be used to query information about the current user.",
"type": "OAuthException",
"code": 2500
}
}
an this point I'm confused. I've tried publishing an action to my timeline, but it tells me a I need an active access token, which I've provided. So how can I publish an action?
When using an app access token please use the ID of the user not /me. You are doing actions on behalf of the app not directly of the user.
User Access Token
https://graph.facebook.com/me/fotoferret:hug?ferret=http://www.example.com/pumpkinpie.html&access_token=MY_ACCESS_TOKEN
App Access Token
https://graph.facebook.com/ID/fotoferret:hug?ferret=http://www.example.com/pumpkinpie.html&access_token=MY_ACCESS_TOKEN
When using the Graph Explorer be sure to switch the option to POST and not get GET. GET is set by default so it will return the actions not create one.
Or using cURL
curl -F 'access_token=MY_ACCESS_TOKEN' \
-F 'ferret=http://www.example.com/pumpkinpie.html' \
https://graph.facebook.com/ID/fotoferret:hug
If you have "Requires App Token to Publish" enabled and get
{"error":{"message":"(#15) This method must be called with an app access_token.","type":"OAuthException","code":15}}
It means you are using
curl -F 'access_token=MY_ACCESS_USER_TOKEN' \
-F 'ferret=http://www.example.com/pumpkinpie.html' \
https://graph.facebook.com/me/fotoferret:hug
Use MY_APP_TOKEN. If you get,
{"error":{"message":"An active access token must be used to query information about the current user.","type":"OAuthException","code":2500}}
it means you are using
curl -F 'access_token=MY_APP_TOKEN' \
-F 'ferret=http://www.example.com/pumpkinpie.html' \
https://graph.facebook.com/me/fotoferret:hug
You should use the numeric id
curl -F 'access_token=MY_APP_TOKEN' \
-F 'ferret=http://www.example.com/pumpkinpie.html' \
https://graph.facebook.com/ID/fotoferret:hug
If you get
{"error":{"message":"(#200) Requires extended permission: publish_actions","type":"OAuthException","code":200}}
The user doesn't have publish_actions actions in their set for me/permissions, it should be there as "publish_actions": 1 if it is not, grant the permission by selecting "Get Access Token" and choosing (you must change to suit in your app code scope as well)
It might be easier if you use the graph API explorer to generate an access token for you app and use that. That would at least eliminate any chance of error from your fetching the access token.
Related
I'm new to Google APIs and I've been trying for days to use a service account to upload content to a Google Cloud Storage bucket. I'm able to accomplish this, but only with a temporary access token obtained from the Google API playground, and I need to be able to get new access tokens so the service account can always upload content.
I've been experimenting with the following, but I keep getting access denied, even though the account in question has 'owner' permissions.
curl -X POST / -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \ -H "Content-Type: application/json; charset=utf-8" \ -d #Documents/request.json \ https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/content-uploader#kol-hatorah-kulah.iam.gserviceaccount.com:generateAccessToken
response:
{ "error": { "code": 403, "message": "The caller does not have permission", "status": "PERMISSION_DENIED" } }
When I run gcloud config list I get the correct project, and the account is my work email, which is also in Google Cloud as an owner.
Thanks in advance!
DISCLAIMER - my solution works for Workload Identity Federation
related problems.
I've had hard time with this error, but finally found it!
For me it was wrong attribute mapping.
I was following some tutorial (which probably went outdated) and mapping was different than from official github action task documentation (here)
I had repository_owner and aud. Changed it for repository and...
It works!
To sum up my mapping looks like this:
"google.subject" = "assertion.sub"
"attribute.actor" = "assertion.actor"
"attribute.repository" = "assertion.repository"
So if you got here because of same tutorial... you've been served!
Your curl command is attempting to use a service account identity to generate an Access Token. The command is failing because you do not have permission.
Add the role roles/iam.serviceAccountTokenCreator to the identity running the command.
I am trying to get setup so that I can view my Nest equipment on my home automation system. Now with the Google Device Access, I have multiple steps that must be completed. I have created the project in Device Access. I setup the OAuth2 credentials. I enabled the api in the Google Cloud Portal. I "linked" the account / OAuth2 cred to my project to get the "authorization-code".
Now I am failing to "Get an Access Token".
When I try to use Google's Template and fill in the OAuth2-Client-ID, OAuth-Client-Secret and Authorization Code, the copy/paste it into a terminal session, I get: "curl: (3) URL using bad/illegal format or missing URL".
If instead I create my curl statement myself, using the data, I get '{
"error": "invalid_client",
"error_description": "Unauthorized"
}'
How do I get to the next step to get an Access Token?
I just had the same problem. The curl command automatically generated on the Google instruction page https://developers.google.com/nest/device-access/authorize did not work.
From Google (and not working) :-
curl -L -X POST 'https://www.googleapis.com/oauth2/v4/token?
client_id=oauth2-client-id&
client_secret=oauth2-client-secret&
code=authorization-code&
grant_type=authorization_code&
redirect_uri=https://www.google.com'
This did work:-
curl -L -X POST 'https://www.googleapis.com/oauth2/v4/token?' -d 'client_id=oauth2-client-id' -d 'client_secret=oauth2-client-secret' -d 'code=authorization-code' -d 'grant_type=authorization_code' -d 'redirect_uri=https://www.google.com'
Just replace oauth2-client-id, oauth2-client-secret, authorization-code with your values.
If the requested access token is not passed back to you and you get this response instead :-
{
"error": "invalid_grant",
"error_description": "Bad Request"
}
This means the authorisation code has been used or has been passed in a request that failed and you need to regenerate the device authorisation code - the authorisation_code in the curl request - using the same process you followed to get it the first time.
I am trying to use Cognito User Pool to authenticate with a PC application using an HTTPS call. I want to obtain the various tokens that I can then use to access the AWS resources without storing AWS secrets in the PC application.
The AWS documentation documents the InitiateAuth method and shows the AWS Endpoints, but it is not immediately apparent how to make the call over HTTPS. Most calls would require an AWS signature, but the InitiateAuth call should not, if I am just submitting Username and Password.
After some poking around, I was able to use the AWS CLI to successfully obtain tokens with this command:
aws cognito-idp initiate-auth --auth-flow USER_PASSWORD_AUTH --client-id the_cognito_client_id --auth-parameters USERNAME=the_users_email,PASSWORD=the_users_password
Where the_cognito_client_id is an approximately 26 character long string shown as App client id under General Settings / App clients.
Note that the USER_PASSWORD_AUTH flow is not enabled by default, so you will initially get an error with this. Go to the Cognito Console for the specific User Pool and look for General Settings/App Clients, click "Show Details" for your specific app client, and check the "Enable username password based authentication (ALLOW_USER_PASSWORD_AUTH)" and save.
Once you get back tokens and you know your call is working, you can use the aws history show command to show you the details of the actual https call. The first time you call
aws history show
You will get a message
Could not locate history. Make sure cli_history is set to enabled in the ~/.aws/config file
Go to that file and add
cli_history=enabled
Then, run your initiate-auth call again with the cli. Then, when you run
aws history show
You will get back the details of how the call was made. (At this point, you might consider removing the cli_history setting so you don't log all of your calls, with all of the credentials, in the future.) You will see
to URL: https://cognito-idp.us-east-1.amazonaws.com/
which tells you the URL to use, and you will see that it is a POST. You will note that "InitiateAuth" is not anywhere in that URL. However, you will see the headers include:
"X-Amz-Target": "AWSCognitoIdentityProviderService.InitiateAuth"
and
"Content-Type": "application/x-amz-json-1.1"
You need both of those headers, including the non-standard Content-Type, to make the HTTPS call work. You can use Postman to put the call together, although Postman does not like the non-standard Content-Type, so you have to turn off the standard Content-Type and manually add these two headers to the call. At that point, Postman is able to obtain the tokens as well.
Postman also provides an export to CURL function (click the link that says "Code"), which gives you:
curl --location --request POST 'https://cognito-idp.us-east-1.amazonaws.com/' \
--header 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
--header 'Content-Type: application/x-amz-json-1.1' \
--data-raw '{
"AuthFlow": "USER_PASSWORD_AUTH",
"AuthParameters": {
"PASSWORD": "the_users_password",
"USERNAME": "the_users_email"
},
"ClientId": "the_cognito_client_id"
}'
Submitting that on the command line also gives you the tokens you need.
To refresh using the refresh token, just use InitiateAuth, but the AuthFlow is REFRESH_TOKEN_AUTH and the only member of AuthParameters is REFRESH_TOKEN (which is, of course, the RefreshToken)
Now, I just need to figure out how to do USER_SRP_AUTH using HTTPS.
The other answer explains how to get the Tokens using the Username and Password. Next, we need to get the temporary credentials from the Cognito Identity Pool. This appears to require two steps. First, we need to call cognito-identity get-id and then cognito-identity get-credentials-for-identity
The get-id call requires the Identity Pool ID, which can be obtained from the Cognito Console for the Identity Pool. The identity-pool-id is available under "edit identity pool" as "identity pool ID." The Login key name comes from the User pool ID and is available under Authentication Providers / Cognito under the Edit Identity Pool. The Login key name is actually provided as "iss" in the encoded ID Token. You can use a service like https://jwt.io/ to decode the ID Token, and it will include an entry like
"iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_zAgxxxxxx"
You can use that, without the https://, as the key for Login. The value for Login is the JWT returned as "IdToken" from InitiateAuth.
Therefore, using the CLI, the first call is
aws cognito-identity get-id --identity-pool-id "us-east-1:aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" --logins "{\"cognito-idp.us-east-1.amazonaws.com/us-east-1_zAgxxxxxx\": \"ThisIsTheVeryLong.IDTokenReturneFrom.TheCognitoUserPool\"}"
Which returns the ID:
{
"IdentityId": "us-east-1:11111111-2222-3333-4444-555555555555"
}
Then, we need to get the temporary credentials using get-credentials-for-identity. This call uses the IdentityId returned from get-id rather than the Identity Pool ID used by get-id. The Login JSON is the same as for get-id. Therefore, the call is:
aws cognito-identity get-credentials-for-identity --identity-id "us-east-1:11111111-2222-3333-4444-555555555555" --logins "{\"cognito-idp.us-east-1.amazonaws.com/us-east-1_zAgxxxxxx\": \"ThisIsTheVeryLong.IDTokenReturneFrom.TheCognitoUserPool\"}"
Which returns something like:
{
"IdentityId": "us-east-1:11111111-2222-3333-4444-555555555555",
"Credentials": {
"AccessKeyId": "ASIAXXXXXXXXXXXXXXXX",
"SecretKey": "Im0JN4PrvZZZZZZZZZZZZZZZZZZZZZZZZZZ/Y/XX",
"SessionToken": "ExtremelyLongSessionToken",
"Expiration": "2020-06-07T15:28:51-07:00"
}
}
You can then use that AccessKeyID and SecretKey to make any needed AWS calls; these temporary credentials are good for an hour.
Using the same methodology with aws history show and Postman described above, we can get the CURL equivalents:
curl --location --request POST 'https://cognito-identity.us-east-1.amazonaws.com/' \
--header 'X-Amz-Target: AWSCognitoIdentityService.GetId' \
--header 'Content-Type: application/x-amz-json-1.1' \
--data-raw '{
"IdentityPoolId": "us-east-1:aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"Logins": {
"cognito-idp.us-east-1.amazonaws.com/us-east-1_zAgxxxxxx": "ThisIsTheVeryLong.IDTokenReturneFrom.TheCognitoUserPool"
}
}'
and then
curl --location --request POST 'https://cognito-identity.us-east-1.amazonaws.com/' \
--header 'X-Amz-Target: AWSCognitoIdentityService.GetCredentialsForIdentity' \
--header 'Content-Type: application/x-amz-json-1.1' \
--data-raw '{
"IdentityId": "us-east-1:11111111-2222-3333-4444-555555555555",
"Logins": {
"cognito-idp.us-east-1.amazonaws.com/us-east-1_zAgxxxxxx": "ThisIsTheVeryLong.IDTokenReturneFrom.TheCognitoUserPool"
}
}'
Note that the CLI converts the expiration timestamp to local time. When you call this with CURL, the "Expiration" value will be something like 1.591572729E9 . You can convert that to a human time with a site like https://www.epochconverter.com/
I am trying to make a POST request to the Facebook API to create instant articles, like so:
curl \
-F 'access_token={access token}' \
-F 'html_source="<!doctype html><html>blah blah blah</html>"' \
-F 'published=true' \
-F 'development_mode=false' \
https://graph.facebook.com/{page-id}/instant_articles
I am an admin for the app, and when I debug my access token, the scope shows email, pages_show_list, pages_manage_instant_articles, public_profile, but the request returns this error:
{"error":
{"message":"(#200) Requires pages_manage_instant_articles permission to manage the object",
"type":"OAuthException",
"code":200,
"fbtrace_id":"Exyv2VtZ5m4"}
}
Anyone have any ideas about what's going on? Thanks and let me know if you need more info!
Solved! I added the version to the url.
https://graph.facebook.com/v2.7/{page-id}/instant_articles
When I first worked with Graph API I faced the same issue but that was in Android.
Although the solution in my case, user / admin have to sign in first and give permission to access facebook data using GraphAPI
I have an app and I want to post to the users feed.
All the users have allowed publish_stream permission but I have no idea how to post to their feeds which I should be able to do even if the user is offline.
I want to use curl and the graph like this:
curl -F 'access_token=...' \
-F 'message=Hello, Arjun. I like this new API.' \
https://graph.facebook.com/arjun/feed
Do I simply use the access code I got when the users initially allowed me access, or do I have to get a new access code each time I want to post to their feed, if so, how do I do that?
Any help, much appreciated.
After the user authorized your application you get an access-token from facebook. You can use this token to post to the users-wall until he changes his password or removes your application from his application list.
I think you need to include your api-key in the request. Otherwise please provide the error message your getting!