Firebase Auth REST API - signing in with email/password doesn't return refresh token - firebase

When I post a sign-in request to https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<API_KEY>, the response body is missing the refresh token and expiration time even though the sign-in operation itself succeeds. It looks like this:
{
"kind": "identitytoolkit#VerifyPasswordResponse",
"localId": <LOCAL_ID>,
"email": <EMAIL>,
"displayName": "",
"idToken": <ID_TOKEN>,
"registered": true
}
It does return an id token, but I've tried using that to authenticate RTDB requests (in the form of <DATABASE_URL>/.../node.json?auth=<ID_TOKEN>) and they fail with HTTP error 401 even though my database has public read/write rules.
The response body returned by a sign-up request (https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=<API_KEY>) doesn't have the same problem.
How do I fix this?

You need to pass returnSecureToken set to true in the request as documented in the REST API docs.

Related

Firebase Realtime Database returns 401 when trying to authenticate?

I am using REST API in my app to communicate with a Firebase RTDB, and trying to use a Google Access Token to authenticate my requests.
My issue is that with even the most permissive Rules on the database, I get HTTP error 401 in response to queries that try to authenticate.
For example, say I try to put some data in my database with the following command, I get 401 in return (all the values within < > are placeholders):
curl -XPUT -d '{ "UserID" : "<GOOGLE_UID>", "UserName" : "Clicksurfer", "CompletionMoves" : 8, "CompletionTime" : 16.21979 }' https://<FIREBASE_URL>.firebaseio.com/Level2/<GOOGLE_UID>.json/?access_token=<GOOGLE_ACCESS_TOKEN>
401
The strangest part is, when I abandon the use of access token altogether the query works:
curl -XPUT -d '{ "UserID" : "<GOOGLE_UID>", "UserName" : "Clicksurfer", "CompletionMoves" : 8, "CompletionTime" : 16.21979 }' https://<FIREBASE_URL>.firebaseio.com/Level2/<GOOGLE_UID>.json
200
As I said, I am currently using the most permissive rules for debugging:
{
"rules": {
".read": true,
".write": true
}
}
Any idea what might be causing this? Thanks in advance
EDIT:
I use the Google Play Games plugin for Unity in my project, among other things to get the AuthCode.
In order to do this, I needed to do a couple of things:
When building the config for Google Play Games during startup, I made sure to call the RequestServerAuthCode(false) method
Have the user login after Google Play Games sets up
Make sure that the relevant ClientID was supplied to Unity (in this case, it is a web client that has auth permissions on my Firebase rtdb).
This all looks like this:
public class GPGSAuthentication : MonoBehaviour
{
public static PlayGamesPlatform platform;
void Start()
{
if (platform == null)
{
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().RequestServerAuthCode(false).Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.DebugLogEnabled = true;
platform = PlayGamesPlatform.Activate();
}
Social.Active.localUser.Authenticate(success =>
{
if (success)
{
Debug.Log("GSPS - Logged in successfully");
}
else
{
Debug.Log("GSPS - Falied to login");
}
});
}
}
Now that we've done this, we can call PlayGamesPlatform.Instance.GetServerAuthCode() in order to get the AuthCode.
I traded in my AuthCode for an Access Token by sending a POST request to https://www.googleapis.com/oauth2/v4/token. In my query, I supply 4 fields:
client_id, which has the ID of the previously used client (where we got the AuthCode from).
client_secret, which has the correlating secret.
grant_type, which is always with the value "authorization_code"
code, which has the value of the AuthCode we got.
In response, I get a 200 response with 4 parameters:
access_token, the token I (fail to) use when authenticating against my Firebase rtdb.
token_type, the type of the aforementioned token.
expires_in, the amount of time before the token expires (I presume in seconds unit)
refresh_token, a token which can be used in order to get a new access_token without having to keep the Google user connected.
I then supply this access_token value to the queries I send to my DB, and promptly get the 401 error.

Delete all users from the new firebase auth emulator

I'm playing around with the new firebase auth emulator (on the node admin SDK), and have made some tests that run perfectly if I manually delete the created users between each test, but I can't seem to automatically delete them?
I've used the endpoint defined here in my beforeEach(), but I get an "Response code 401, unauthorized" back from the response call?
Endpoint: delete: http://localhost:9099/emulator/v1/projects/{project-id}/accounts
I just tried using Postman to send the call, and it responded with the following:
{
"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.",
"errors": [
{
"message": "Login Required.",
"domain": "global",
"reason": "required",
"location": "Authorization",
"locationType": "header"
}
],
"status": "UNAUTHENTICATED"
}
}
The URL in the error didn't seem to give me much help beyond adding a google button to a web app, which pointed me to creating an OAuth2 web account. I entered the localhost:9099 into my existing one, but don't know where I should use the client ID and the client secret? If they are what I should use at all.
I know I need some sort of Authorization header for the delete call, but I just don't get what I should put in that header, or how.
Thank you for any insight into this.
Edit: I've now tried the following Authorization headers:
"admin"
"" (an empty string)
The full token generated by firebase.options.credential.getAccessToken()
The access_token field of the above token
The id_token field of the above token.
The token itself looks like this (redacted some fields):
{
"access_token":
"[access token string here]",
"expires_in": 3599,
"scope":
"openid https://www.googleapis.com/auth/firebase https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/cloudplatformprojects.readonly",
"token_type": "Bearer",
"id_token":
"[id token string here]"
}
Thanks! However, I wanted using this with a curl format to get this on a npm script, so here is what I used:
curl -H 'Authorization: Bearer owner' -X DELETE http://localhost:9099/emulator/v1/projects/<projectid>/accounts
the response should be:
{}
I figured it out! When the admin generates a token, I use the access_token field part of this token and add the header Authorization: 'Bearer' + access_token to the delete request. Thanks for the help.
(This is an emulator-only endpoint)
Edit: I could just use the string "owner" as the token... Took me a while to get that, but now it works.

No refresh token while authorizing Device Access

I am able to successfully authorize a user through Partner Connections Manager, but when I request tokens from https://www.googleapis.com/oauth2/v4/token using my authorization code, I do not receive a refresh_token in the response, only an access_token is present:
{
access_token: 'my-access-token',
expires_in: 3599,
scope: 'https://www.googleapis.com/auth/sdm.service',
token_type: 'Bearer'
}
Make sure to specify access_type=offline in your Partner Connections Manager (PCM) URL. Omitting it assumes access_type=online, which does not provide a refresh token.
For example, the PCM URL should look something like this, where access_type=offline:
https://nestservices.google.com/partnerconnections/project-id/auth?
redirect_uri=my-redirect-uri&
access_type=offline&
prompt=consent&
client_id=my-client-id&
response_type=code&
scope=https://www.googleapis.com/auth/sdm.service
Then, the subsequent token response from https://www.googleapis.com/oauth2/v4/token should have what you expect:
{
"access_token": "my-access-token",
"expires_in": 3599,
"refresh_token": "my-refresh-token",
"scope": "https://www.googleapis.com/auth/sdm.service",
"token_type": "Bearer"
}
For more information, see Authorize an Account on the Device Access site.

how to push notification from postman to firebase?

I'm Trying to push notification from postman to firebase for testing
I posted using documentation tips and response is success but nothing sent to my android device .. I tested my code using debugging and firebase console and it working well but when i used postman nothing happens
This is my posting format
http://fcm.googleapis.com/fcm/send
Content-Type : application/json
Authorization: key=AAAAitv2sYo:APA91bENlw37p5pa7pMIKoVv8CroevA7tK3tVFNGUchhGf_zkeKVFdQeYcKQmxsg-2ZOkNHMAvloRjTugmZHzNBa_TLMR2_7lffglJvrKHT1TNixHxtXZimWi2f7c16M2M7ic2S5g1gC
{
"notification" :
{
"body" : "hello",
"title": "firebase",
"sound": "default"
},
"to" : "AAAAitv2sYo:APA91bENlw37p5pa7pMIKoVv8CroevA7tK3tVFNGUchhGf_zkeKVFdQeYcKQmxsg-2ZOkNHMAvloRjTugmZHzNBa_TLMR2_7lffglJvrKHT1TNixHxtXZimWi2f7c16M2M7ic2S5g1gC"
}
i used authorization and to is the same key " server key "
and the response is
{
"multicast_id": 9063339683658826188,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [
{
"message_id": "0:1533133178192931%0000000000000000"
}
]
}
Note : When i write https posting is failed and got Could not get any
response error when i made it http it get the above response
another question .. can i see the sent message in firebase console ?
The Authorization key in the header and the to property in the message have different purposes and are never the same value.
The Authorization key validates your request to the Firebase server. Its value is the "Server key" shown in the Cloud Messaging tab of your Project settings at the Firebase console.
The message to value is the registration ID of the device to which you are sending the message. It is obtained from a call to a client-side SDK.

Access token request results in 302 in Angular HttpClient

I'm trying to authenticate requests for WordPress rest-api using grant type password. OAuth2 authentication in WordPress is provided by WP OAuth Server plugin.
When I request access token using Postman Chrome app the server responds with expected access token object but the similar request doesn't work in Angular. It gives status 302 and due to xhr redirect to login page, I'm not able to get access token object. I'm using Angular 5.
Here's how I request access token in Angular:
/* Example token url
AuthProvider.TOKEN_URL:
https://www.example-wordpress.com/oauth/token
*/
const body = {
grant_type: 'password',
username: username,
password: password,
};
const headers = new HttpHeaders()
.set('Authorization', 'Basic ' + btoa(AuthProvider.CLIENT_ID + ':' + AuthProvider.CLIENT_SECRET));
this.http.post(AuthProvider.TOKEN_URL, body, { headers: headers });
The above request produces 302 with location header set to:
https://www.example-wordpress.com/login/?redirect_to=https%3A%2F%2Fwww.example-wordpress.com%2Foauth%2Ftoken
And then a xhr GET request is made to above location which responds with HTML of login page and hence no access token is obtained.
The similar POST request for access token in Postman works fine and results in expected access token object but I can't get it to work in Angular.
EDIT
While debugging I generated JavaScript code for access token request from Postman and pasted in console of Chrome after importing jQuery.
The request works as expected in console as well and no redirection occurs. The response is JSON with access token.
Here's the code Postman generated for the POST request:
var settings = {
"async": true,
"crossDomain": true,
"url": "https://example-wordpress.com/oauth/token",
"method": "POST",
"headers": {
"content-type": "application/x-www-form-urlencoded",
"authorization": "Basic M0wzakE3d080VmxxbXB0UUF1dUI5RkxicWxmeE8yR25Zdk4xQmxvbTp4TktTYnJ1Mno5cEp2VDFMbTNGNFhEQm10eDZzUGsya1FqZDg3VmQ2",
"cache-control": "no-cache",
"postman-token": "46339abe-2d1a-1032-f5d8-36e3193d9a81"
},
"data": {
"grant_type": "password",
"username": "my-username",
"password": "my-password",
"client_id": "3L3jA7wO4VlqmptQAuuB9FLbqlfxO2GnYvN1Blom",
"client_secret": "xNKSbru2z9pJvT1Lm3F4XDBmtx6sPk2kQjd87Vd6"
}
}
$.ajax(settings).done(function (response) {
console.log(response);
});
And here's the response logged from above code:
{
access_token: "rksen3p351fj0povsrpfv2eeuahrciglc3ilphhy",
expires_in: 3600,
token_type: "Bearer",
scope: "basic",
refresh_token: "fudju8tecbnwly2e1xgfv92tykvpsniwkfpvrd7d"
}
I'm unable to figure out why redirection occurs when we request through Angular and not responds with access token JSON.
Any help is appreciated.
access_token (which I imagine is what you expect to have) isn't part of the few headers that Angular is able to read without setting up your server.
Angular only read "basic" headers such as Content-type. This is because of the default CORS configuration that only reads Cache-Control, Content-Language, Content-Type, Expires, Last-Modified and Pragma. When it comes to custom headers, you have to tell your server to expose the headers.
This is done through the Access-Control-Expose-Headers header.
There was no problem at all. It was a very very silly mistake. I apologize.
I was testing with two websites simultaneously and both had similar configuration. The only difference was that one had OAuth plugin installed and other not. So when I tried to authorize the request from Angular with the website which hadn't had OAuth2 plugin installed and so redirected to the login page. The constant set for the AuthProvider.TOKEN_URL was incorrectly set, while when I was testing with other tools I was using correct url.
Anyway, this was all my mistake. It happens sometimes, when you don't take break. :)

Resources