Using the Firebase Admin SDK for .NET in Google Cloud Run

Hiranya Jayathilaka
Firebase Developers
7 min readJun 9, 2019

--

Recently I was reading Patrick Martin’s article on deploying a C# backend in Google Cloud Run, and I figured it would be fun to write a follow up piece featuring the Firebase Admin SDK for .NET. Hence, in this post I show how to implement a custom authentication service in C#, and deploy it as a serverless API using Cloud Run. This service validates user credentials, and uses the Admin SDK to generate signed custom tokens that clients can use to sign into Firebase.

Google Cloud Run is one of the latest additions to Google’s serverless portfolio. It enables developers to deploy any Docker container as a serverless application in the cloud. This means you no longer have to code your serverless apps using a specific set of programming languages or APIs. Any application can be deployed in Cloud Run as long as it is:

  1. stateless,
  2. has an HTTP interface, and
  3. can be packaged as a Docker container.

Patrick’s article clearly outlines how to deploy any generic ASP.NET Core application using Cloud Run. The basic idea is to develop the app using the .NET Core and the dotnet command-line utility, and then package it into a Docker image. Microsoft provides official .NET Core Docker images that can be used as the basis for this. Finally, the Dockerized application is deployed to Cloud Run using the gcloud tool. You can use the exact same steps to package and deploy an application that uses the Firebase Admin SDK for .NET. Therefore we will mainly focus on the additional steps you need to follow when using the Admin SDK.

First, you need to add the Admin SDK dependency to your project. Having initialized your .NET web project, you can add the Admin .NET SDK to it by running the following command.

$ dotnet add package FirebaseAdmin --version 1.6.0

Version 1.6.0 is the latest available at the time of this writing. Check the Admin SDK documentation to see if there’s a more recent version available.

Next, we need to initialize the Admin SDK. We can do this in the Startup class of the web application as shown in listing 1.

Listing 1: Initializing the Firebase Admin SDK

Note that we are not passing any arguments to the FirebaseApp.Create() method. When initialized this way, the Admin SDK will automatically discover the required authorization credentials from the runtime environment. This mechanism works out of the box on all application runtimes managed by the Google Cloud Platform including Cloud Run.

Our Startup class also engages the MVC support in ASP.NET, which means we will be implementing our request processing logic in a controller class. Listing 2 shows what this looks like.

Listing 2: Verifying user credentials and creating a Firebase custom token

Our controller is programmed to respond to POST requests on the /login URL. It accepts a JSON payload containing custom user credentials. We then query our custom user store to validate the credentials sent by the client. The UserStore class is just a stand-in for the actual database or the API where your app’s (or organization’s) user information is stored. In our example it just contains two fake user accounts — alice and bob — with hard-coded credentials.

If the credentials are valid, we use the FirebaseAuth API of the Admin SDK to create a signed custom token. The client (usually a mobile or web app) can then use this custom token to complete the Firebase authentication flow.

Full source code of this web application is available in GitHub. To test it locally, download a service account JSON file from your Firebase project, and set it to your environment.

$ export GOOGLE_APPLICATION_CREDENTIALS=path/to/service-account.json

Now run the following command to build and launch the app.

$ dotnet run

This starts a web server on local port 5000. You can send some requests to the service to verify its behavior. If all goes well, the application responds back with a signed token when valid credentials are presented.

$ curl -v -X POST -d '{"username": "alice", "password": "password"}' -H "Content-type: application/json" localhost:5000/login
> POST /login HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.47.0
> Accept: */*
> Content-type: application/json
> Content-Length: 45

< HTTP/1.1 200 OK
< Date: Sat, 08 Jun 2019 21:56:52 GMT
< Content-Type: application/json; charset=utf-8
< Server: Kestrel
< Transfer-Encoding: chunked
<
{"customToken":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9......

All other requests fail with HTTP 401 Unauthorized responses.

$ curl -v -X POST -d '{"username": "alice", "password": "incorrect"}' -H "Content-type: application/json" localhost:5000/login
> POST /login HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.47.0
> Accept: */*
> Content-type: application/json
> Content-Length: 46

< HTTP/1.1 401 Unauthorized
< Date: Sat, 08 Jun 2019 21:58:51 GMT
< Content-Type: application/json; charset=utf-8
< Server: Kestrel
< Transfer-Encoding: chunked
<
{"error":"Incorrect username or password"}

At this point we can go ahead and deploy the application to Google Cloud Run. Again I refer you to Patrick’s article for the relevant instructions. The deployment process mainly involves creating a Dockerfile that describes how to build and package our code as a Docker image. Then we kick off a new build in Google Cloud Build which takes our code and Dockerizes it. The resulting image is saved to the Google Container Registry. Finally, we deploy this Docker image to Cloud Run to be executed as a serverless application.

$ export PROJECT_ID=my-gcp-project-id
$ gcloud config set project $PROJECT_ID
$ gcloud builds submit --tag gcr.io/${PROJECT_ID}/custom-auth-service
$ gcloud beta run deploy --image gcr.io/${PROJECT_ID}/custom-auth-service

Now our application is deployed and ready to serve traffic. The final deployment command displays the Cloud Run endpoint that accepts incoming requests.

Please specify a region:
[1] us-central1
[2] cancel
Please enter your numeric choice: 1
Service name (custom-auth-service):
Allow unauthenticated invocations to [custom-auth-service] (y/N)? Y
Deploying container to Cloud Run service [custom-auth-service] in project [solarflares-f4bee] region [us-central1]
✓ Deploying new service... Done.
✓ Creating Revision...
✓ Routing traffic...
✓ Setting IAM Policy...
Done.
Service [custom-auth-service] revision [custom-auth-service-00001] has been deployed and is serving traffic at https://custom-auth-service-example-uc.a.run.app

However, there are couple more things we need to do before we can run a successful trial. Remember that we have set up the Admin SDK to automatically discover credentials from the Cloud Run environment. It will also use the Google Cloud IAM service to sign custom tokens. Therefore we need to complete the following one-time configuration steps to ensure successful operation of our code.

  1. Enable the Cloud IAM API for your project. This can be done by visiting the APIs & services page in the Google Cloud console.
  2. Authorize the Cloud Run credentials to sign tokens. This can be done by visiting the IAM & admin page in the Google Cloud console, and granting the Service Account Token Creator role to the Default compute service account.

Admin SDK documentation provides more details on accomplishing these tasks. Once that’s done, we are ready to try our shiny new serverless app.

$ curl -v -X POST -d '{"username": "alice", "password": "password"}' -H "Content-type: application/json" https://custom-auth-service-example-uc.a.run.app/login
> POST /login HTTP/1.1
> Host: custom-auth-service-example-uc.a.run.app
> User-Agent: curl/7.47.0
> Accept: */*
> Content-type: application/json
> Content-Length: 45

< HTTP/1.1 200 OK
< content-type: application/json; charset=utf-8
< X-Cloud-Trace-Context: d35d7da733bd98697940d035c2de9dbd;o=1
< Date: Sat, 08 Jun 2019 21:15:06 GMT
< Server: Google Frontend
< Content-Length: 752
< Alt-Svc: quic=":443"; ma=2592000; v="46,44,43,39"
<
{"customToken":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9....

In this post we looked at how to use the Firebase Admin SDK for .NET in Google Cloud Run. We showed how to automatically discover Firebase credentials from the runtime, and use them to mint Firebase custom authentication tokens that are signed by the Google Cloud IAM service.

Most serverless platforms restrict developers to specific programming languages and/or APIs. Google Cloud Run on the other hand enables developers to bring all their favorite programming languages, libraries and frameworks to the cloud. Developers can continue to implement their backend components in languages they know and love, and use Cloud Run to deploy them as serverless apps at scale. Moreover, Cloud Run is based on open standards and opensource technologies like Docker and Knative. The end result is a very powerful, convenient and cost-effective platform that developers can use without the fear of vendor lock-in.

We did use a couple of additional Google Cloud services in our development flow — Cloud Build and Google Container Registry. But those are optional. We could just as well build the image ourselves using Docker tools, and upload it to a container registry of our choice. Cloud Run is agnostic of how and where the Docker images are stored, as long as they are accessible.

The Firebase Admin SDK for .NET is still somewhat new, and therefore doesn’t support all the APIs that you will find in the other Admin SDK implementations. But thanks to an enthusiastic open source community, many of the key Firebase Authentication APIs and Cloud Messaging APIs are now available in it. If you’re using Firebase Unity and a fan of .NET, this package (and Cloud Run) might unlock a whole new way of implementing backend components for your Firebase games. Check out the example app as well as the Admin SDK for .NET, and let me know what you think.

--

--

Hiranya Jayathilaka
Firebase Developers

Software engineer at Shortwave. Ex-Googler. PhD in CS. Enjoys working on cloud, mobile and programming languages. Fan of all things tech and open source.