I have written a simple web app hosted in Firebase and using Firebase Functions (for API layer) and Firebase Authentication to manage and authenticate users. The web client layer is written using Polymer including Polymerfire and is using to handle user auth. I only accept Google ids for users.
The drawing below gives some more details.
Web Client Flow:
<firebase-auth
> tag using with the Firebase Authentication componentI've read all the documentation and many SO posts (including Linking Google Assistant with Firebase Auth about implementing Account Linking for AoG/Dialogflow, but I am thoroughly confused. The material I've found assumes a level of knowledge I don't have and I can't seem to acquire :-)
I would like to use:
Can anyone direct me to documentation, tutorial, or sample application that can provide clear instructions to achieve this?
The problem is that there are few clear tutorials for how to do this because every authorization situation is different. It is compounded in your case because you're not really looking for authorization - you're looking for authentication. But Google and the Assistant need to treat this as authorization. Specifically - they want to make sure that the user on their end of the Google Home is authorized to access your service.
This process is called Account Linking in Google's documentation. You're linking a Google Assistant user to your user account system.
To do this, they're going to use OAuth... but backwards from how you're currently using it. In your current model, your web client uses OAuth (through the Google Login) to get the authorization through Google's servers. But with the Assistant - the Assistant is the client, and it needs to get that authorization through your server.
Here is an update to your diagram that tries to illustrate this, although this is simplified a bit. Google's documentation gives step-by-step implementation requirements, although it can't give any details or code since those are dependent on your needs. The numbers refer to each step, which I talk about below.
Your user has triggered your Action, or a step in your Action, that requires authorization. All requests go through Google's server (before hitting Dialogflow), and it knows if it will need to provide that authorization information.
If it already has authorization, we can skip to step 6.
If it doesn't already have authorization, it will contact your OAuth server at an authorization page that you've configured. It does this by directing your user to open the Home app, which will redirect the user to that authorization page. Skip to step 3.
If it had authorization, but that authorization has expired, it will contact your OAuth server at the token exchange point to exchange a refresh token for an auth token. Skip to step 4.
The user will likely need to sign-in and your server will need to authenticate them (a bunch of arrows that mirror what your web-app is doing, so I omitted them). Typically, you'll also explicitly make sure that the user is authorizing the Google Assistant to have access to their resources on your service. (Google shows OAuth screens all the times for third-parties getting access to your resources stored on Google. You've probably seen them.) Your auth server needs to send back a limited-use code which we'll exchange for a refresh token and auth token shortly.
Your auth server now gets either a refresh token or an access code (depending on what happened in steps 2 and 3). Your server then needs to take this, verify that it is valid, and then generate an auth token (and, if this is the first time, a refresh token.) When you verify it, you'll likely be consulting your user database, possibly to store the tokens, but certainly to make sure the user is still a user.
You'll then return the auth token (and possibly refresh token) to Google's servers. They'll store these tokens - the refresh token indefinitely, and the auth token for the lifetime of the token.
For each request, Google will pass the auth token to Dialogflow...
...which will pass it on in the JSON body to the webhook.
Your webhook will then need to get this auth token out of the JSON body (or by using app.getUser()
) and convert it to the ID you need. One way to do this is to have an API in your auth server that takes the auth token and returns the ID. Or you may be able to look it up in the database directly, if you're using a shared user database. Or the auth token may be a signed JWT and, once you've verified the signature is from your auth server, you can use the id that is included in the JWT.
You can then proceed as you've outlined.
I've used the Authorization Code Flow for this for a few reasons:
It is more secure than the Implicit flow.
It is not significantly more complex to implement.
The thing that does make it more complex (the code exchange endpoint) is required if you want to do the "Simplified"/"Streamlined" Identity Flow, which allows users to sign-up to your service if they haven't already done so.
I do not go into the additional requirements to get the Streamlined Flow working. Get the above working first and then follow the directions to add the streamlined account creation, which mostly involve extra work at stage 2, 4, and 5.