Firestore REST API make authenticated request with http-client - rest

I want to get data from a firestore via the REST API. I'm using an HTTP-Client (Webstorm) and do the following.
First I authenticate with Google which works fine and does return a token:
POST https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<firebase-api-key>
Accept: application/json
Content-Type: application/json
{
"email": "some#email.com",
"password": "notthispassword"
}
But then, trying to get data from the firestore (not realtime-db) like this
GET https://firestore.googleapis.com/v1/projects/<projectId>/databases/(default)/documents/<collection>
Accept: application/json
Authorization: Bearer <token from auth response>
it keeps telling me:
{
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. 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"
}
}
These are my firestore security rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
I would be happy if somebody could tell me where I am going wrong here.

The first part of the solution was to read the response carefully. It containes the following link https://developers.google.com/identity/sign-in/web/devconsole-project.
Then I had to understand that if you are using the google-identitiy-toolkit you kind of left the firebase-realm and must append the api-key generated in the GC-console (not the firebase-key!) (https://console.cloud.google.com/apis/credentials) to the URL used to fetch the data like this:
GET https://firestore.googleapis.com/v1/projects/<projectId>/databases/(default)/documents/<collection>?key=<google-cloud-api-key>
Accept: application/json
Authorization: Bearer <token from auth response>

Related

Cloud Run Service requests always fail with 401 when using JWT returned for another service. The same request works with JWT returned for end-user

I have an app consisting of multiple Cloud Run Services. Each service is open only to a specific set of other services.
Let's say I have 2 services with URLs https://api-service-123.run.app and https://data-provider-service-123.run.app. The first service also has a custom URL https://api.my.domain.
api-service needs access to data-provider-service. So, following the documentation, I created two per-service user-managed service-accounts api-service-account#domain and data-provider-service-account#domain. I added api-service-account#domain into data-provider-service with Cloud Run Invoker role.
Now, I have trouble accessing the account with ID Token returned from Google. I tried several ways. Firstly, I utilized slightly adjusted code from the docks
export const getToken = async (url: string, targetAUD?: string) => {
const auth = new GoogleAuth();
const request = async () => {
if (!targetAUD) {
targetAUD = new URL(url).origin;
}
console.info(`request ${url} with target audience ${targetAUD}`);
const client = await auth.getIdTokenClient(targetAUD);
const res = await client.request({url});
console.info(res.data);
return res.data;
}
try {
return await request();
} catch (err) {
console.error(err);
}
}
When the function above is called as getToken('http://data-provider-service-123.run.app');, the request fails with 401 Unauthorized.
I also tried to call it as getToken('https://data-provider-service-123.run.app'); and got a response 403 Forbidden. The following entry is added to data-provider-service logs for each such request
{
httpRequest: {9}insertId: "60fcb7e0000c12346fe37579"
logName: "projects/my-project/logs/run.googleapis.com%2Frequests"
receiveTimestamp: "2021-07-25T01:01:20.806589957Z"
resource: {2}
severity: "WARNING"
textPayload: "The request was not authorized to invoke this service. Read more at
https://cloud.google.com/run/docs/securing/authenticating"
timestamp: "2021-07-25T01:01:20.800918Z"
trace: "projects/my-project/traces/25b3c13890aad01234829711d4e9f25"
}
I also tried to obtain and use JWT from compute metadata server (also a way advertised in the docs) by running curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=http://data-provider-servive-123.run.app" \ -H "Metadata-Flavor: Google".
When I execute this code in Cloud Shell, I get JWT that looks like this
{
"iss": "accounts.google.com",
"azp": "123456789-9r9s1c4alg36erliucho9t52n12n6abc.apps.googleusercontent.com",
"aud": "123456789-9r9s1c4alg36erliucho9t52n12n6abc.apps.googleusercontent.com",
"sub": "106907196154567890477",
"email": "my_email#gmail.com",
"email_verified": true,
"at_hash": "dQpctkQE2Sy1as1qv_w",
"iat": 1627173901,
"exp": 1627177501,
"jti": "448d660269d4c7816ae3zd45wrt89sb9f166452dce"
}
Then I make a request using postman to https://data-provider-service/get-data with a header Authorization: "Bearer <the_jwt_from_above>" and everything works fine
However, if I make the same request from my api-service, the JWT returned is
{
"aud": "http://data-provider-service-123.run.app",
"azp": "111866132465987679716",
"email": "api-service-account#domain",
"email_verified": true,
"exp": 1627179383,
"iat": 1627175783,
"iss": "https://accounts.google.com",
"sub": "111866132465987679716"
}
If I make the same request with the postman and place this JWT into the Authorization header, the 401 Unauthorized is returned.
I have spent this week trying to solve this issue. I triple-checked the permissions, redeployed the services several times, but nothing helps.
I changed http to https in the URL of the target service when asking computing metadata server, and looks like it solved the problem. Requesting token like this with google-auth-library still fails with 403 error.
I'll update that answer if the solution is sustainable.

How to add API key to Axios post request for mailchimp

I'm trying to set up an axios post request to add members to an audience list, but I can't figure out how to add the API key (keeps giving error 401: 'Your request did not include an API key.'). I've tried a bunch of things in the "Authorization" header, like what I put below (also: "Bearer ${mailchimpKey}", "${mailchimpKey}", "Bearer ${mailchimpKey}", "Basic ${mailchimpKey}", and probably more...).
I also don't know what the "username" would be, but "any" worked when I tested the API elsewhere.
Does anyone know how I should set this up?
axios
.post(
`https://${server}.api.mailchimp.com/3.0/lists/${list_id}/members`,
{
email_address: email,
status: "subscribed",
},
{
"User-Agent": "Request-Promise",
Connection: "keep-alive",
Authorization: `Basic any:${mailchimpKey}`,
// Testing on localhost
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
}
)
If your intention is to use HTTP Basic authentication, just use the Axios auth config option
axios.post(
`https://${server}.api.mailchimp.com/3.0/lists/${encodeURIComponent(list_id)}/members`,
{
email_address: email,
status: "subscribed",
},
{
auth: {
username: "anystring",
password: mailchimpKey
},
headers: { // personally, I wouldn't add any extra headers
"User-agent": "Request-Promise"
}
}
)
HTTP Basic auth headers look like
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
where the string after "Basic" is the Base64 encoded "username:password" string. Axios provides the auth option as a convenience so you don't need to encode the string yourself.
Some other problems you had were:
Adding request headers outside the headers config option
Attempting to send Access-Control-Allow-Origin and Access-Control-Allow-Headers as request headers. These are response headers only. Adding them to your request will most likely cause more CORS errors

API request does not authenticate

Using this documentation I'm trying to test the request using Postman the example on the right side:
$ curl https://subscriptions.zoho.com/api/v1/organizations
-H 'Authorization: Zoho-oauthtoken 1000.41d9f2cfbd1b7a8f9e314b7aff7bc2d1.8fcc9810810a216793f385b9dd6e125f'
-H 'X-com-zoho-subscriptions-organizationid: 10234695'
Maybe I'm not setting the parameters right but this is how it looks for the moment.
A new GET Request, in the url input: https://subscriptions.zoho.com/api/v1/organizations
And under that, in the Headers tab I added two key-value pairs:
Authorization: Zoho-oauthtoken 1000.41d9f2cfbd1b7a8f9e314b7aff7bc2d1.8fcc9810810a216793f385b9dd6e125f
Authorization: X-com-zoho-subscriptions-organizationid: 1023469
The returned result:
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
</body>
</html>
If I deleted the second key-value pair it returns this JSON:
{
"code": 57,
"message": "You are not authorized to perform this operation"
}
What is wrong with my approach?
Can you try this?
If you are sure of the api url, do validate the token and create a fresh token and
add it to header as below:
HeaderName : Authorization
HeaderValue: 1000.41d9f2cfbd1b7a8f9e314b7aff7bc2d1.8fcc9810810a216793f385b9dd6e125f
HeaderName : X-com-zoho-subscriptions-organizationid
HeaderValue: 10234695
I tried this and is getting,
{
"code": 14,
"message": "Invalid value passed for authtoken."
}
Might be the token got invalid.
Now I tried with a new token generated myself and I am getting now,
{
"code": 0,
"message": "success",
"organizations": [],
}
In short, you have to generate an auth token first and then hit the url with proper header value as shown above.
Thank you :)

"Resource Not Found" message received when sending a query to Keen IO API

I am using Advanced REST Client tool to test a data pull from the Keen IO API, and think getting the request right, but not getting the data. Getting "resource not found" error. This can also be done via CURL.
Headers: Authorization:
Content-Type: application/json
actual request: GET /3.0/projects//queries/saved/Sponsorships/result HTTP/1.1
HOST: api.keen.io
authorization:
content-type: application/json
Base URL used: https://api.keen.io
Any ideas as to what may be doing wrong?
The saved query name is capitalized "Sponsorships". Make sure your saved query name is lower-cased, not camel or title-cased. To be sure that you are getting the correct saved query name.
Also, you may want to first obtain a list of all saved queries as a reference:
GET /3.0/projects/<project_name>/queries/saved HTTP/1.1
HOST: api.keen.io
authorization: <your_key>
content-type: application/json
You will get something like this:
[
{
"refresh_rate": 0,
"last_modified_date": "2016-12-20T01:09:54.355000+00:00",
"query_name": "",
"created_date": "2016-12-20T01:09:54.355000+00:00",
"query": {
"filters": [],
"latest": 100,
"analysis_type": "extraction",
"timezone": "UTC",
"timeframe": "this_30_days",
"event_collection": ""
},
"metadata": {
"visualization": {
"chart_type": "table"
},
"display_name": ""
},
"run_information": null
}
]
FWIW, I also have seen the "Resource not found" error when writing data to an event if the project is not correctly set up. For example, passing in the wrong project_id or write_key or if the project was deleted from your Keen.io account.

dotmailer request token from REST API

I struggle in call the REST API at Dotmailer.
he provide a document for call the OAuth and get the token.
but it's always throws the same error.
Input is
Post Method
URI: https://r1-app.dotmailer.com/OAuth2/Tokens.ashx
JSON input is
{
"client_id" : "apiuser-XXXXXXXXXXX#apiconnector.com",
"redirect_uri" : null,
"client_secret" : "XXXXXXXXXXXX",
"grant_type": "authorization_code",
"code":"MyServerCode",
"test_mode":true
}
Out put is
{
"error": "invalid_request",
"error_description": "There was a problem with the 'grant_type' parameter: The parameter is required."
}
Anyone know the error.
Thanks in advance...
I think Dotmailer OAuth have some problem.
I was used alternatively Basic Authentication method to access the dotmailer API.
Base URI = https://api.dotmailer.com/v2/
Header
Content-type: application/json
Authorization: Basic base64_convertion(username:password).
Sample
Content-type: application/json
Authorization: Basic XXXXXXXXXXXXXXXX.
Use WADL method.
https://api.dotmailer.com/v2/help/wadl