Firebase REST Authentication

Hello,

In this article I will show you how to authenticate to Firebase and secure the databases with some simple security rules. I’m using this setup for my NucuCar project.

Authentication

The first step is to enable the Email/Password sign in method, by going to the Authentication and clicking the Sign-In Method tab:

Next, we can add a manual user by clicking Users tab and Add user.

Now, to login with our newly created user, we make a POST request with a json body to the following endpoint:

// POST https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=WEB_API_KEY 
{
     "email": "your_user@email.com",
     "password": "your_password",
     "returnSecureToken": true
 }

Note that you need to fill in the WEB_API_KEY parameter as well! You can obtain it by clicking the settings gear next to Project Overview. The General tab should open and it should list the Web API Key.

If the login is successful you will get a response similar to the following:

{
  "kind": "identitytoolkit#VerifyPasswordResponse",
  "localId": "drH5pThXcuY1V2w2FSVwlaRZXEN2",
  "email": "xx.xx@xx.xx",
  "displayName": "",
  "idToken": "xx.xx.xx-xx-xx-xx",
  "registered": true,
  "refreshToken": "xx-xx-xx",
  "expiresIn": "3600"
}

In order to make authenticated requests you’ll have to provide the following header to all requests:

Authentication: Bearer ${idToken}

Keep in mind that the idToken expires in 3600 seconds and you’ll need to exchange the refresh token for a new idToken before or after it expires:

// https://securetoken.googleapis.com/v1/token?key=WEB_API_KEY
{
  "grant_type": "refresh_token",
  "refresh_token": your_refresh_token
}

Security Rules

To secure my database I’ve used the following security rules. The don’t allow deletion and only allow creating, updating and reading documents. Deleting them is forbidden.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow delete: if false;
      allow create, update, read: if (request.auth != null && request.auth.uid != null);
    }
  }
}

Thanks for reading!

Firebase Rest on Raspberry Pi

I’ve tried to use Google’s Firebase with the Firebase Admin SDK in my C# project. The good news is that the Admin SDK is easy to use and all you need to do is call two methods. The authentication part is handled by an environment variable which points to some .json file which you download. The bad news is that the SDK depends on gRPC and the dotnet version of it doesn’t work well on the Raspberry Pi.

What I’m going to do is to replace the admin SDK with simple REST API calls, this way I can post data to Firebase from anywhere, at this moment I only want to post data from the Raspberry Pi.

I’ve been browsing the REST API Reference docs in in order to figure it out how to make requests and after some time of experimenting and reading the documentation I’ve translated by hand a simple telemetry request from my Raspberry Pi into a restful Firebase request.

This is how it looks like in the Firebase format:

PATCH https://firestore.googleapis.com/v1/projects/project_name/databases/(default)/documents/collection_name/doc_id

{
	"name": "batman",
	"fields": {
		"source": {
			"stringValue": "NucuCar.Sensors"
		},
		"timestamp": {
			"timestampValue": "2019-12-01T23:26:13.5537227+02:00"
		},
		"data": {
			"arrayValue": {
				"values": [
					{
						"mapValue": {
							"fields": {
								"sensor_state": {
									"integerValue": 2
								},
								"cpu_temperature": {
									"doubleValue": 48
								},
								"_id": {
									"stringValue": "CpuTemperature"
								}
							}
						}
					},
					{
						"mapValue": {
							"fields": {
								"sensor_state": {
									"integerValue": 2
								},
								"temperature": {
									"doubleValue": 32
								},
								"humidity": {
									"doubleValue": 100.0
								},
								"pressure": {
									"doubleValue": 6222
								},
								"voc": {
									"doubleValue": 0.0
								},
								"_id": {
									"stringValue": "Bme690-Sensor"
								}
							}
						}
					}
				]
			}
		}
	}
}

All what’s left to do now is to write a translator which translates raw C# dictionaries into the format from above. I want to reuse this without much hassle if my telemetry data format changes.

After a bit of trial and error I’ve managed to implement a translator, thus completely dropping the dependency for Firebase’s Admin SDK. I haven’t implemented authentication handling yet, but it’s on my board.

Thank you for reading!