I'm trying to set up a REST API server that could send push notifications using Firebase. Google documentation says this is a valid POST request, as a start :
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"topic" : "foo-bar",
"notification" : {
"body" : "This is a Firebase Cloud Messaging Topic Message!",
"title" : "FCM Message",
}
}
}
However, I can't figure out which Authorization bearer is expected here. There is a ton of them on the firebase console, and I've tried each and every one of them, none work. They all result in 401 response.
Where can I find the expected bearer for this request ?
Thanks !
I find it easier to use legacy protocols to send push notifications. We just need the Server key which can be found in the Firebase Console.
Firebase Console > Project Settings > Cloud Messaging > Server Key
HTTP request looks like this:
curl -X POST -H "Authorization: key=<your_server_key>" -H "Content-Type: application/json" -d '{
"notification": {
"body" : "This is a Firebase Cloud Messaging Topic Message!",
"title" : "FCM Message",
},
"to": "/topics/<topic_name>"
}' "https://fcm.googleapis.com/fcm/send"
Check Server Reference for other APIs for server implementation.
So, first of all go to Google Cloud Console and choose APIs&Services->Credentials. From there click on +Create Credentials->OAuth Client ID (Interface changes all the time so try to find this option). And then, simply choose Add Key and it will give you a json file.
After you receive your json file you can try what was given in this guide: https://firebase.google.com/docs/cloud-messaging/auth-server.
If you want to send request from Postman then you can try https://developers.google.com/oauthplayground. Register there with your google account and from available services select Firebase Cloud Messaging API v1 -> https://www.googleapis.com/auth/firebase.messaging. There in the second step press Exchange authorization code for tokens. Finally, you will get your Access and Refresh Token there
Related
I am trying to enable Firebase Authentication in my project, and to add Phone Auth to it, via API (without using the GUI console).
I am using the Service Usage API in order to enable Identity Toolkit, and then trying to use Identity Toolkit API in order to add the Phone Auth.
I am enabling Identity Toolkit via the Service Usage API like this (POST request):
URL:
https://serviceusage.googleapis.com/v1/projects/MY_GCP_PROJ/services:batchEnable
Body:
{
"serviceIds": ["identitytoolkit"]
}
And indeed, after running this request I see in GCP console that Identity Toolkit has been enabled.
After that, I try to update the config using Identity Toolkit API, like this (PATCH request):
URL:
https://identitytoolkit.googleapis.com/v2/projects/MY_GCP_PROJ/config?updateMask=signIn
Body:
{
"signIn": {
"phoneNumber": {
"enabled": true,
"testPhoneNumbers": {
"+11111111111": "123456",
}
},
}
}
But for some reason, I receive an error saying:
{
"error": {
"code": 404,
"message": "CONFIGURATION_NOT_FOUND",
"status": "NOT_FOUND"
}
}
I can't understand why the Identity Toolkit API cannot find the configuration and update it as specified.
Does anyone know how it can be solved?
Thank you
I spent days config Firebase Auth without using Web UI :).
Even checking the GCP audit log to see what backend call enables Firebase Auth.
However, I could not find the CreateConfig method at https://cloud.google.com/identity-platform/docs/reference/rest.
I tried this method and things work.
https://cloud.google.com/identity-platform/docs/reference/rest/v2/projects.identityPlatform/initializeAuth
curl --request POST \
--url "https://identitytoolkit.googleapis.com/v2/projects/$ENV_GCP_PROJECT_ID/identityPlatform:initializeAuth" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--header "X-Goog-User-Project: $ENV_GCP_PROJECT_ID"
But the result is the new Identity Platform will be used instead of the old Identity Toolkit.
Looking at pricing, it seems (a bit) more expensive https://firebase.google.com/pricing.
I personally will use the new one (as Google is pushing it :).
Hope this answer somehow helps (or anyone can find the REST call to enable auth for the old Identity Toolkit)
The same issue happened to me when I was trying to use REST API but then I get to know that the URL I am using was wrong.
Try Method: projects.updateConfig
I have simple test callable function deployed via firebase deploy --only functions.
Here it's content:
export const test = region('europe-west1').https.onCall((data, context) => {
logger.debug('test call info', data, context);
return 'hello, world!';
});
I can successfully call it by doing HTTP call to https://europe-west1-{project}.cloudfunctions.net/test and recieve {"result": "hello, world!"}.
Now want to protect this function via IAM policies.
I create new service account and load it's credentials json.
I go to console and remove from allUsers a Cloud Functions Invoker role and add service account created in #1 with Cloud Functions Invoker role.
<--- Now I recieve 403 Forbidden when I try to call my test function, as expected
I create id-token with my service account at my PC
const auth = new GoogleAuth({keyFile: './key.json'});
targetAudience = new URL('https://europe-west1-{project}.cloudfunctions.net/test');
const client = await auth.getIdTokenClient(targetAudience as string);
const idToken = await client.idTokenProvider.fetchIdToken(targetAudience as string);
console.log(idToken);
I verify my token is correct and issued for the right service account via https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={{id-token}}.
I call my endpoint with Authorization: Bearer {{id-token}} header.
I get 401 Unauthorized error with JSON telling me
{
"error": {
"message": "Unauthenticated",
"status": "UNAUTHENTICATED"
}
}
I'm in pain since after reading most of google cloud docs, SO (1, 2), etc. it seems that I do everything right but still get this error.
UPD1: providing additional info to #DazWilkin
1.
gcloud auth activate-service-account cloud-functions-invoker#{project-id}.iam.gserviceaccount.com --key-file="key.json"
Activated service account credentials for: [cloud-functions-invoker#{project-id}.iam.gserviceaccount.com]
gcloud projects get-iam-policy {project-id}
...
- members:
- serviceAccount:cloud-functions-admin#{project-id}.iam.gserviceaccount.com
- serviceAccount:cloud-functions-invoker#{project-id}.iam.gserviceaccount.com
role: roles/cloudfunctions.invoker
...
I copy this value gcloud auth print-identity-token | clip
Here is what I get after calling https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={{id-token}}
{
"aud": "32555940559.apps.googleusercontent.com",
"azp": "cloud-functions-invoker#{project-id}.iam.gserviceaccount.com",
"email": "cloud-functions-invoker#{project-id}.iam.gserviceaccount.com",
"email_verified": "true",
"exp": "1629157648",
"iat": "1629154048",
"iss": "https://accounts.google.com",
"sub": "114693730231812960252",
"alg": "RS256",
"kid": "6ef4bd908591f697a8a9b893b03e6a77eb04e51f",
"typ": "JWT"
}
I make this curl (copied from postman). I've also tried same curl with command-line - got same result.
curl --location --request POST 'https://europe-west1-{project-id}.cloudfunctions.net/test' \
--header 'Authorization: Bearer
{token}
' \
--header 'Content-Type: application/json' \
--data-raw '{
"data": {
"goodbye": "world:("
}
}'
UPD2: new input
This behaviour is observed only with callable functions https.onCall(). If I use https.onRequest() things work fine but I'm still confused about onCall behaviour, since it seems that I implement protocol correctly (see my curl).
OMG!!!!!
TL;DR: callable functions are only for end users authenticated with firebase auth and can't be used with IAM tokens. Only way to use them is with roles/cloudfunctions.invoker assigned to allUsers.
The thing is... I was looking into callable functions protocol specification here: https://firebase.google.com/docs/functions/callable-reference.
It says:
The HTTP request to a callable trigger endpoint must be a POST with the following headers:
...
Optional: Authorization: Bearer
A Firebase Authentication user ID token for the logged-in user making the request. The backend automatically verifies this token and makes it available in the handler's context. If the token is not valid, the request is rejected.
I was thinking specification means that we shall pass our service account id-token here and I was trying to do so (such as with onRequest functions). BUT SUDDENLY, token is interpreted differently there. It's a user token which is obtained through firebase auth. And it's even stated in the documentation one level deeper (1, 2):
Warning: The ID token verification methods included in the Firebase Admin SDKs are meant to verify ID tokens that come from the client SDKs, not the custom tokens that you create with the Admin SDKs. See Auth tokens for more information.
Missing this warning costed me 3 days of pain.
i configured apiKey in huawei console for PushKit and i want send push from web app to my android app, so i prepared following CURL:
problem is postman still return
{"error":"400 Bad Request, body is empty"}
when i'm trying to call url from any online curl console result is as following:
{
"msg": "Authentication Error",
"code": "80200001"
}
how can i authorize my request by apiKey?
UPDATE
"code": "80200001"
It's recommended that you check your appid in the URL.
This error code is usually caused by the appid in your URL is different from the appid used to obtain the access_token, or the appid has no permission.
As mentioned above, my App has the r_emailaddress permission activated in its scope settings.
When I retrieve the oauth2 access token and use it to get data from the authenticated user I will get all fields except the email address.
Here is my request:
curl -H "Authorization: Bearer $LI_ACCESS_TOKEN" "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,email-address)?format=json" -X GET
Returns
{
"firstName": "John",
"id": "som31d",
"lastName": "Doe"
}
I noticed that when I use the JS SDK all requested data is returned. So where comes the deviation come from ?
I found the problem. I issued the request for the authorization code with the scope parameter containing only the r_basicprofile permission.
Provide r_emailaddress additionally to get them E-Mail address.
Correct:
curl -i "https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=clientid&redirect_uri=http://localhost:8088&state=987654321&scope=r_basicprofile,r_emailaddress" -X GET
Swift + Vapor framework for server + Xcode 8.1
I am trying to read Firebase Realtime Database making HTTP requests to my DB, but I get permission denied.
These are the steps:
1. create JWT sign it with secret key downloaded from "console.developers.google.com"
2. send POST request to OAuth2 server and get access token
3. send GET request to firebase database with access token received from OAuth2 server.
I get "Permission denied", HTTP/1.1 403 Forbidden
// the header of the JSON Web Token (first part of the JWT)
let headerJWT = ["alg":"RS256","typ":"JWT"]
// the claim set of the JSON Web Token
let jwtClaimSet =
["iss":"firebase-adminsdk-kxx5h#fir-30c9e.iam.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/firebase.database", //is this the correct API to access firebase database?
"aud":"https://www.googleapis.com/oauth2/v4/token",
"exp": expDate,
"iat": iatDate]
drop.get("access") { request in
var accesstoken = "ya29.ElqhA-....XXXX"
let responseFirebase = try drop.client.get("https://fir- 30c9e.firebaseio.com/data/Users.json",
headers: ["Authorization":"Bearer \(accesstoken)"],
query: [:])
print("FirebaseResponse_is \(responseFirebase)")
return "success"
}
TLDR; Try placing auth=<TOKEN> in your query string instead of using the authorization header.
The Firebase documentation is unclear on how this works. According to the documentation, there are three methods that should work.
auth=<TOKEN> in query string (link)
access_token=<TOKEN> in query string (link)
Authorization: Bearer <TOKEN> in request header (link)
I'm not convinced that all three methods do actually work however. I'm using method 1 in my application, so I know that one works for sure.
The scope key was missing value https://www.googleapis.com/auth/userinfo.email
let jwtClaimSet =
["iss":"firebase-adminsdk-kxx5h#fir-30c9e.iam.gserviceaccount.com",
"scope": "https://www.googleapis.com/auth/firebase.database
https://www.googleapis.com/auth/userinfo.email",
"aud":"https://www.googleapis.com/oauth2/v4/token",
"exp": expDate,
"iat": iatDate]
I found the answer browsing google groups here
headers: ["Authorization":"Authorization: Bearer \(accesstoken)"],
should be
headers: ["Authorization":"Bearer \(accesstoken)"],