Google Sheets API v4 append request receives HTTP 401 response for public feeds using API Key - google-sheets-api

This is extremely similar to another question answered here about how to GET spreadsheet data, but I'm trying to append data to a spreadsheet. Here's my sample curl request:
curl -H "Content-Type: application/json" -X POST -d '{"range":"A1","majorDimension":"ROWS","values":["Frank2"]}' https://sheets.googleapis.com/v4/spreadsheets/{SPREADSHEET_ID}/values/A1:append?valueInputOption=RAW&key={API-KEY}
Here's the response:
{
"error": {
"code": 401,
"message": "The request does not have valid authentication credentials.",
"status": "UNAUTHENTICATED"
}
}
Can this be done only using an API Key or am I doing something wrong? The documentation suggests it is possible if the spreadsheet is shared publicly.

Requests that write to the spreadsheet require authentication credentials. Even if the spreadsheet is shared publicly, when writing through the API the write must be attributed to a user.

This is currently broken. You can not edit the document (even if public) with only an APIKey.
https://issuetracker.google.com/issues/73974970

https://developers.google.com/sheets/api/guides/authorizing#APIKey
The page above states the following:
Your application must use OAuth 2.0 to authorize requests. No other authorization protocols are supported. If your application uses Google Sign-In, some aspects of authorization are handled for you.

Related

How to use "user context access token" that I get from Twitter OAuth 1.0a in my request?

I have successfully (?) implement the Twitter three-legged authentication process to obtain user access token. The problem is the access token appears invalid... or I use it wrong. I already able to get the app's access token, which can access limited Twitter API. I use it by adding "Authentication: Bearer 'access token'" on the header. But when I did the same thing with the user context access token and did the same request, I always get error code 89 Invalid or expired token.
The access token I obtained has a structure of [several numerics]-[some alpha numeric chars]. Like 12345678-asd98f798asdf79asdfa9sdfs9df7a9sdf7. This looks similar with the access token example in step 3 of https://developer.twitter.com/en/docs/basics/authentication/oauth-1-0a/obtaining-user-access-tokens.
I also notice that the example request there is like this:
POST statuses/update.json
oauth_consumer_key=cChZNFj6T5R0TigYB9yd1w
oauth_token=7588892-kagSNqWge8gB1WwE3plnFsJHAZVfxWD7Vb57p0b4
Which I presume those two additional parameters are to be added to the body instead of the header. But, how if my request is a GET request? Like request to get home timeline, which absolutely requiring user context access token?
https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline
From this API ref, the example only give the GET url, and not how to supply the user context access token. Please help. I have the feeling that the solution is very simple (like a fix on the header), but I can't see it.
This is my current request:
curl -X GET \
'https://api.twitter.com/1.1/users/show.json?screen_name=huffpost' \
-H 'Authorization: Bearer 12345678-as3d12a3d1a3sd1232ads13asd123as1d23as3d32,Bearer 12345678-as3d12a3d1a3sd1232ads13asd123as1d23as3d32' \
This is the result:
{
"errors": [
{
"code": 89,
"message": "Invalid or expired token."
}
]
}
The user access token requires signing a request which includes parameters and headers.
https://developer.twitter.com/en/docs/basics/authentication/oauth-1-0a/authorizing-a-request
You can use a library like https://github.com/twitter/joauth to generate the signature.
For Java+OkHttp - you can use this library https://github.com/yschimke/okurl/blob/master/src/main/kotlin/com/baulsupp/okurl/services/twitter/joauth/Signature.kt#L33

Using CURL to edit entries on google sheets documents

After some confusion, I did get reading from a public sheet working:
curl https://sheets.googleapis.com/v4/spreadsheets/[sheetID]/values/A1?key=[MyAPIKey]
Where Sheet ID is from google sheets, and [MyAPIKey] is from https://developers.google.com/sheets/api/guides/authorizing#APIKey
It gives me read-access to the sheet.
As soon as I try to write to any cells on the sheet (despite them being publicly writable) it gives me an error. I can easily edit them anonymously from my browser without any keys, however, I can't seem to edit them at all without API keys.
If I issue:
curl https://sheets.googleapis.com/v4/spreadsheets/[sheetid]/values/Sheet1\!A1?valueInputOption=RAW?key=[MyAPIKey] -X PUT -d "{\"values\":[ [ \"Test\" ] ] }"
I receive:
{
"error": {
"code": 401,
"message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status": "UNAUTHENTICATED"
}
}
I think this is related to Google Sheets API v4 append request receives HTTP 401 response for public feeds using API Key
I'm avoiding the OAUTH2 mechanism as for this task, I can't allow applications access to entire google drive. How can this be done with selective link-based access, like is done via the authkey approach? Is there some other way to give sheet-at-a-time access in OAUTH2?
Nope, you can't perform Sheet operations using CURL alone. Error 401 means you need access tokens to work on that sheet. So you need to use OAuth flow to get rid of that error and also make sure to define the scope.
There's a bunch of quickstarts below the Introduction to Sheets that you can use.

Amazon Cloud Drive REST api endpoint

I am building a program that will list albums/folders and images from my Amazon Cloud Drive. I am able to authenticate and get a token by following the instructions here at amazon public apis.
I am having trouble with the next call to get my endpoints described here under Account API.
Using get
GET : {{metadataUrl}}/account/endpoint Gets the customer end-point against
which REST queries will be executed.
So my request looks just like this in fiddler and on my site just like it is described on the Amazon site here under Get Endpoint. The only differences is the token for obvious reasons.
Sample Request:
GET /drive/v1/account/endpoint HTTP/1.1
Host: drive.amazonaws.com
Authorization: Bearer
Atza|IQEBLjAsAhQ5zx7pKp9PCgCy6T1JkQjHHOEzpwIUQM
My response is:
{
"message":"Authorization header requires 'Credential' parameter.
Authorization header requires 'Signature' parameter.
Authorization header requires 'SignedHeaders' parameter.
Authorization header requires existence of either a 'X-Amz-Date'
or a 'Date' header. Authorization=Bearer"
}
What I am expecting:
{
"customerExists": true,
"contentUrl": "https://content-na.drive.amazonaws.com/cdproxy/",
"metadataUrl": "https://cdws.us-east-1.amazonaws.com/drive/v1/"
}
I did find some information about building the objects in my response from amazon, however, it's not listed in the documentation on the amazon developer site. Is this something new that has not been updated in the docs or am I doing something wrong?
I had a new line between Authorization: Bearer and my token Atza|IQEBLjAsAhQ5zx7pKp9PCgCy6T1JkQjHHOEzpwIUQM. After removing the new line my issue was fixed..

Google OpenIdConnect People

I implemented the client Side of OpenIDConnect authentication/provisioning/federation for few OAuth2-OpenIdConnect providers. But I fail to get Google OpenID People https://developers.google.com/+/api/openidconnect/getOpenIdConnect working.
I have no problem with the 1st part of OpenID Authentication/Authorization and get the Identity token from JSONWEBtoken without trouble. Nevertheless I fail to access the $identityApiUrl. The odd thing is that the old google's userinfo API works!!! Only the new one fails with an authorization error.
For PeopleAPI I used a Bearer token reusing the access_token, I got with my authorization request. Exactly like I do with the old API.
Here after a short extract from my code with the URL and scopes I used, as well as the error, I get when replaying manually with a curl the request.
Questions:
Is there a special authentication method for OpenIdConnect People API ?
Do I need to request special authorization in the application console ?
Extract from code with API's URL
// main IDP configuration URLs
protected $openidconnect = true; // Google supports OpenID-Connect
protected $authTokenUrl = 'https://accounts.google.com/o/oauth2/auth';
protected $accessTokenUrl= 'https://www.googleapis.com/oauth2/v3/token';
// I fail to get Google People OpenIdConnect API to work :(
//protected $identityApiUrl= 'https://www.googleapis.com/plus/v1/people/me/OpenIdConnect';
protected $identityApiUrl= 'https://www.googleapis.com/oauth2/v1/userinfo';
// OAuth2 action-1: getAuthUrl($state) build authorization token url
protected $scopes = ['openid','email','profile']; // request authentication & email
The error code, when replaying the request with curl
[apache#vz-bzh GeoToBe]$ curl -X GET -H "Authorization: Bearer ya29.5ABSl_75eP_zYFho_E-wVjPlZJc1XfY398HZqJjMxvRxBEWteLKZwNeh2v0BPwWuoH1iLpESeBQvFw" https://www.googleapis.com/plus/v1/people/me/openIdConnect
{
"error": {
"errors": [
{
"domain": "usageLimits",
"reason": "accessNotConfigured",
"message": "Access Not Configured. The API is not enabled for your project, or there is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your configuration.",
"extendedHelp": "https://console.developers.google.com"
}
],
"code": 403,
"message": "Access Not Configured. The API is not enabled for your project, or there is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your configuration."
}
}
you need to enable the "Google+ API" under APIs & auth in the Google API console.

Creating a fork with the GitHub V3 API (REST)

I'm trying to fork a repo using the GitHub V3 API via REST, however, I am having issues making a POST request as per the docs (https://developer.github.com/v3/repos/forks/#create-a-fork).
Basically, what I have so far:
A logged-in user with an OAuth Token
A POST request setup to the API (URL: https://api.github.com/repos/carmichaelalonso/infiniteflight/forks/) - I am testing this with hurl.it to begin with.
Headers in the request: one has the name Authorization with the value 'token ...', the other specifies Content-Type with the value application/json
A body with the following JSON: {"organization" : "shortlisthome"} (shortlisthome is the account I am trying to fork the repo to.
I am not intending to fork this to an organization, instead of a standard user account, which is where I am getting confused. When I run the request, I do not get any authentication errors or 404 errors (I previously had but I had been entering incorrect values by mistake, causing such errors).
When I run this request though, I get the following result (a 422 unprocessable request):
{
"message": "Validation Failed",
"documentation_url": "---url-to-docs---",
"errors": [
{
"resource": "Fork",
"code": "invalid",
"field": "organization"
}
]
}
I am unsure whether or not I am able to fork this to a standard user, or if it is an error with my request. Please let me know if I can provide any more info (first post here so a bit unfamiliar with the convention).
Thanks!
In order for shortlisthome to fork the repository you need to authenticate as them. The repository you're trying to fork is public, so all you need to do is obtain a OAuth token for shortlisthome and then make a similar request to the one you're making now. The only difference will be that you do not need to provide the JSON body of {"organization": "shortlisthome"}.
For what it is worth, the optional JSON body is intended for you to use when you are a member of an organization with proper permissions and you want to fork the repository to that organization. You cannot fork a repository to someone else's account unless you are authenticated as them.
I've so far avoided OAuth2, and do not know hurl. Yet, perhaps this can help.
This post shows how it can be done using cURL's -u username flag:
curl -u 'myusername' https://api.github.com/repos/carmichaelalonso/infiniteflight/forks/ -d ''
The -d (or alternatively --data) flag turns it into a POST request.
Without that flag cURL defaults to a GET request, which is not what you want.
Since, the data is part of the URI for this request, send an empty string for the data that must follow the -d param, as such: -d ''.
Of course, using -u will require you to also supply a password..
Here is what GitHub shows using OAuth2 with their API:
OAuth2 Token (sent in a header):
curl -H "Authorization: token OAUTH-TOKEN" https://api.github.com
OAuth2 Token (sent as a parameter):
curl https://api.github.com/?access_token=OAUTH-TOKEN
Read more about OAuth2. Note that OAuth2 tokens can be acquired programmatically, for applications that are not websites.
OAuth2 Key/Secret
curl 'https://api.github.com/users/whatever?client_id=xxxx&client_secret=yyyy'
I suspect that adding -d '' (or some equivalent in hurl),
plus one of the formats above for sending OAuth2 info might get you most of the way there.
I used this command to fork on github enterprise
curl -vX POST https://git.redacted.com/api/v3/repos/<org-to-fork-from>/<repo-to-fork>/forks?access_token=<api-token> -d #gh-fork.json --header "Content-Type: application/json"
gh-fork.json is just
{
"organization": "org-to-fork-to",
"description": "",
"homepage": "https://git.redacted.com",
"private": false
}