Using Firebase with App Engine users
Tags: appengine, firebase, go
Published: 2018-04-04 10:44:29

---
title: Using Firebase with App Engine users
published: true
description: Firebase and Firestore are amazing developer products from Google, but how can I use an existing auth flow? Example in Go/JS.
cover_image: https://thepracticaldev.s3.amazonaws.com/i/dotv88ws1cwxt2j3x4e0.jpg
tags: appengine, firebase, golang
---

If you've built for App Engine since its inception in 2008, you might have used its authorization flow. It's simple—add `login: required` in `app.yaml`, or require login programmatically—and now you have your users' Google account. 👍

> Q: How do I use that with Firebase, which has its own auth system?

Naïvely, you could throw away your existing auth flows, and use Firebase directly. However, that will disrupt your users—they'll have to sign in again, which could be unexpected. 😲

<hr />

# The Answer

The answer is: **you can't** have your users automagically login with their Google account in Firebase. You ask: then why am I reading this post?! 🤔

So, while Firebase has amazing support for signing in [with multiple providers](https://fir-ui-demo-84a6c.firebaseapp.com/)—even your phone number! 📞—you actually can skip Firebase's signin code completely and create users directly, using the **first strategy** in the diagram below.

![Two possible Firebase user flows](https://thepracticaldev.s3.amazonaws.com/i/o2m0nu1jq7f6cokeea7y.png)

So we can create whole new users and generate what's known as a **Custom Token**, for those users to interact with Firebase's services. These users aren't technically associated with an existing Google account—since only your backend creates them, you can assert their validity.

(The second case is the more traditional model—Firebase has 'providers' for different login systems. But you can't migrate to this if you're using an existing login system, _even if_ that login system 'matches'.)

## Custom Token

To create a Custom Token, you can use the Firebase Admin SDK, which has support for Go, Node.JS, Python and Java.

First—if you're using `dev_appserver`, you'll likely need to set up the credentials to your service account—this is the account that's actually signing you in. Head to the Firebase console's "Settings" &raquo; "Service Accounts" and download the private key. In your shell, run something like:

```bash
export GOOGLE_APPLICATION_CREDENTIALS="/full/path/to/file/serviceAccountKey.json"

# then you can start your app
dev_appserver.py app.yaml
```

> ⚠️ Never store your private key in a public place or check it in!

I'll demonstrate how to use `CustomToken` inside a Go app. Inside the code, you'll need to use the [App Engine user package](https://cloud.google.com/appengine/docs/standard/go/users/reference) to get access to the current user, passing its ID to Firebase's `CustomToken` method:

```go
// 0. create firebase.App
app, err := firebase.NewApp(ctx, nil)
if err != nil { ... }

// 1. get the current App Engine user
u := user.Current(ctx)
if u == nil || u.ID == "" { ... }

// 2. create auth.Auth
client, err := app.Auth(ctx)
if err != nil { ... }

// 3. use auth.Auth to mint a token for an ID, creating the account as nessecary
token, err := client.CustomToken(u.ID)
if err != nil { ... }

// 4. send token to client- profit!
```

### Remember

* The the `CustomToken` method will **transparently** create a user account with the ID you specify—*this is the crux of this guide!*

* While this example uses `u.ID` (the user's email), it could be any unique string. Firebase's built-in providers use [UUIDs](https://groups.google.com/forum/#!msg/firebase-talk/s9mv4S46Qs0/UXD4Tnl2BwAJ) which don't look like email addresses, so it'd be impossible to have collisions.

## Client Integration

Once you've minted the token, you'll need to send it to your client. I'm going to talk about the web, but [Firebase's docs detail native clients](https://firebase.google.com/docs/auth/admin/create-custom-tokens#sign_in_using_custom_tokens_on_clients).

In my projects, I tend to include the token in the first HTML response, so it's immediately available to your code—either via a JS global or an attribute:

```html
<script>window.firebaseToken = '{{TOKEN}}';</script>
<!-- or -->
<body data-firebase-token="{{TOKEN}}">
```

Then in your JS, you can just wait for the auth to complete:

```js
const token = window.firebaseToken || document.body.dataset.firebaseToken;
await firebase.auth().signInWithCustomToken(token);
const user = firebase.auth().currentUser;
console.info('user is', user);
```

From here on in, any requests you make to the Firebase APIs—like the awesome, scalable Firestore real-time database—are authenticated against this user account that you've just created. 🎉

### Remember

* Because this is an account we made up, and not really associated with a Google login, all this token is good for is talking to Firebase. 🔥

* This token expires after an hour, so you have to use it to `signInWithCustomToken` immediately. This might affect you if e.g., the token gets cached inside a Service Worker.

<hr />

That's it—you're done! But there are two extensions:

# 1️⃣ Multiple Auth Providers

Firebase allows you to link multiple auth providers to one account. This gives you two interesting options:

* You can migrate away from App Engine's auth flows, as users naturally sign in and out again
* You can let users sign in with additional accounts, e.g. Facebook, Twitter: which is a powerful feature of Firebase's auth model.

To read more about account linking, [see Google's docs](https://firebase.google.com/docs/auth/web/account-linking).

# 2️⃣ Claims

When you create an account using `CustomToken`, you can also indicate 'claims'. These are essentially tags you can look up later, perhaps when verifying the Firebase token. Some examples might include 'paidAccount', 'restricted', etc.

See the overall docs on [creating Custom Tokens](https://firebase.google.com/docs/auth/admin/create-custom-tokens#create_custom_tokens_using_the_firebase_admin_sdk).

<hr />

# Thanks

I hope you've learned how to integrate your existing App Engine auth flow with Firebase. If you have questions, contact me on Twitter or leave a comment below. ✒️👇