20

Currently Google Assitant includes an easy way to request non-identifiable information about the user and a detailed flow to authenticate the user on a third party service through OAuth2. What about if all I need is have the user authenticate on Google itself? I tried filling in the account linking flow using Google OAuth2 information, but that seems not to work. If that last thing is supposed to work fluently than that would be enough of an answer.

Context: Users already authenticate only with Google on a related webpage. All I need is to link this already authenticated account with the less-authenticated account on Google Assistant.

David Mulder
  • 26,123
  • 9
  • 51
  • 114

4 Answers4

42

Update, 25 Oct 2018:

As of 13 September 2018, there is now a much simpler way to access the user's account if your project uses Google Sign-In. Google Sign-In for Assistant will give you an ID Token with information about the user, including their Google ID, with their permission. This permission can be granted just using voice and is fairly streamlined.

You can combine this with a web- or app-based Google Sign-In to get their permission to access OAuth scopes if you need to access Google's APIs.

Update, 25 Oct 2017:

As of around 4 Oct or 7 Oct, Google has updated their policy (again) to restore language restricting OAuth endpoints that are valid. The terms now include

When implementing account linking using OAuth, you must own your OAuth endpoint

and it appears (from the comments below) that they now check for the Google endpoints to prevent this method from working.

At this point, the only thing you can do is setup your own OAuth2 server.

Original Post:

Broadly speaking, the auth tasks you need to do are in four parts:

  1. Configure your project (in the cloud console) so that the Calendar API is enabled and that the OAuth2 client is correctly configured.
  2. Configure the Action for account linking in the action console.
  3. Configure the Actions on Google Integration for your API.AI Agent to indicate that sign-in is required.
  4. When API.AI calls your webhook to fulfill an Intent, it will include an auth token as part of the JSON. You can use this token to make calls to the Google APIs you need.

Configure Cloud Project

You need to configure your cloud project so that it has access to the Google APIs you need and setup the OAuth2 Client ID, Secret, and Redirect URI.

  1. Go to https://console.cloud.google.com/apis/dashboard and make sure you have the project you're working with selected. Then make sure you have the APIs you need enabled.

  2. Select the "Credentials" menu on the left. You should see something like this:

Credentials screen

  1. Select "Create credentials" and then "OAuth client ID" Create credentials

  2. Select that this is for a "Web application" (it is... kinda...)

  3. Enter a name. In the screen shot below, I used "Action client" so I remember that this is actually for Actions on Google.

  4. In the "Authorized Redirect URIs" section, you need to include a URI of the form https://oauth-redirect.googleusercontent.com/r/your-project-id replacing the "your-project-id" part with... your project ID in the Cloud Console. At this point, the screen should look something like this:enter image description here

  5. Click the "Create" button and you'll get a screen with your Client ID and Secret. You can get a copy of these now, but you can also get them later. enter image description here

  6. Click on "Ok" and you'll be taken back to the "Credentials" screen with the new Client ID added. You can click the pencil icon if you ever need to get the ID and Secret again (or reset the secret if it has been compromised).

enter image description here

Configure the Action Console

Once we have OAuth setup for the project, we need to tell Actions that this is what we'll be using to authenticate and authorize the user.

  1. Go to https://console.actions.google.com/ and select the project you'll be working with.

  2. In the Overview, make your way through any configuration necessary until you can get to Step 4, "Account Linking". This may require you to set names and icons - you can go back later if needed to correct these.

enter image description here

  1. Select the Grant Type of "Authorization Code" and click Next.

enter image description here

  1. In the Client Information section, enter the Client ID and Client Secret from when you created the credentials in the Cloud Console. (If you forget, go to the Cloud Console API Credentials section and click on the pencil.)

  2. For the Authorization URL, enter https://accounts.google.com/o/oauth2/v2/auth

  3. For the Token URL, enter https://www.googleapis.com/oauth2/v4/token

  4. Click Next

enter image description here

  1. You now configure your client for the scopes that you're requesting. Unlike most other places you enter scopes - you need to have one per line. Then click Next.

enter image description here

  1. You need to enter testing instructions. Before you submit your Action, these instructions should contain a test account and password that the review team can use to evaluate it. But you can just put something there while you're testing and then hit the Save button.

Configure API.AI

Over in API.AI, you need to indicate that the user needs to sign-in to use the Action.

  1. Go to https://console.api.ai/ and select the project you're working with.

  2. Select "Integrations" and then "Actions on Google". Turn it on if you haven't already.

  3. Click the "Sign in required for welcome intent" checkbox.

enter image description here

Handle things in your webhook

After all that setup, handling things in your webhook is fairly straightforward! You can get an OAuth Access Token in one of two ways:

  • If you're using the JavaScript library, calling app.getUser().authToken

  • If you're looking at the JSON body, it is in originalRequest.data.user.accessToken

You'll use this Access Token to make calls against Google's API endpoints using methods defined elsewhere.

You don't need a Refresh Token - the Assistant should hand you a valid Access Token unless the user has revoked access.

Prisoner
  • 49,922
  • 7
  • 53
  • 105
  • 2
    I am using a similar approach but with implicit grants and find that it works well when testing with the browser / actions console, and also with the Google Home app for Android. Unfortunately on the iphone version of the app, user auth hangs most of the time. Feedback from actions on google support is that the problem is that google sign in flow is implemented in separate browser tab (window). On iphone you can't open 2 windows in SfariViewController, thus they are re-writing address of the first page and can’t finish sign in flow. This is known issue and they are not planning to change this. – Dana Jun 01 '17 at 06:36
  • The solution is to implement sign in flow all in one browser window. I'm unclear how to do this. Have you tested your approach on iphone? If it works it would be great if you would share your code behind the authorization URL you set up. – Dana Jun 01 '17 at 06:37
  • @Prisoner: Sorry that I didn't reply in time to your comment before you wrote this answer. Regardless, when I run `app.askForSignIn()` I end up getting an error saying `expected_inputs[0].possible_intents[0]: Transactions/Identity API must be enabled`. I have tried enabling a variety of API's on my Project, but without any luck :/ . With a `HarpoonResponse is invalid` in the DebugInfo. – David Mulder Jun 01 '17 at 07:54
  • And of course: Thanks a lot for the response. It seems that my attempt was fairly similar, although I have to say that this seriously could use some polish (speech only?). Regardless, will be very happy once I get this to work :) . – David Mulder Jun 01 '17 at 07:58
  • @DavidMulder - Oooh! Transactions. I hadn't played with those yet, but this is referring to a feature on the Assistant side - not on your project. If your project requires sign-in for the welcoming intent, you won't need to ask for sign-in. (I'll see about updating my response.) – Prisoner Jun 01 '17 at 10:24
  • @Dana - I don't have an iPhone, so haven't been able to test it. I would suggest asking that as a separate question and see if I can find one or pull in someone who is better at iPhone OAuth as well. – Prisoner Jun 01 '17 at 10:25
  • @Prisoner Well, I don't have any interest in using Transactions. It's just that I only need sign in for a very specific subset of features. I assumed that's what `app.askForSignIn()` was for... did I misunderstand that? – David Mulder Jun 01 '17 at 11:20
  • @DavidMulder - Nope, you understood it correctly. But they group that under "Transactions" for nearsighted reasons. (At least partly because the features are still in Beta and don't work on all surfaces yet.) – Prisoner Jun 01 '17 at 11:51
  • @Prisoner Just a quick update: Went through the transaction documentation to see whether there was anything obvious which was missing, but wasn't able to find anything. Tried switching that 'Does your app perform Transactions?' checkbox, but that didn't do anything. – David Mulder Jun 01 '17 at 14:52
  • @ Prisoner - I've gone ahead and done that, question here: https://stackoverflow.com/questions/44311663/actions-on-google-account-linking-on-iphone – Dana Jun 01 '17 at 15:29
  • Did anyone submit an assistant app and got it approved using that approach? As of right now, this isn't allowed by the policy (like I mention in my response afterwards) – Ahmed Mounir Jun 01 '17 at 18:50
  • @Ahmed Mounir you are totally right, it's technically possible but the app is not approved by Google because it doesn't respect the policy :/ – greywolf82 Jun 02 '17 at 06:24
  • 2
    This clearly violated a previous policy, which explicitly stated you needed to control the endpoint and the console enforced that policy, but that rule (and its technical enforcement) was removed from the policy. I have Googlers on the team (including the review team) telling me that it is allowed if you're using Google Sign In, and others telling me it still violates the policy. I'll update the answer once I get a straightforward response. – Prisoner Jun 02 '17 at 11:39
  • 1
    @Prisoner I followed the instructions in this answer (and also tried a few variations like implicit workflow) but it doesn't work. Whenever I invoke the app, I get the response `It looks like your account is not linked yet`. Any ideas as to what I might have missed? – Pravin Sonawane Jun 05 '17 at 03:01
  • @PravinSonawane - That is the correct response if you haven't linked your account yet. I'll update the answer to indicate what that means and how a user should be expected to deal with that. (If you're still getting it even after you link your account - that is a separate question that you should post on StackOverflow.) – Prisoner Jun 05 '17 at 03:12
  • @Prisoner Thanks. I can try your suggestions after you update and post a new SO question if still required. – Pravin Sonawane Jun 05 '17 at 03:13
  • @Prisoner I've been struggling with this for a couple of weeks now. I don't think I've been as happy to see an access token my whole life. – Lizozom Jun 15 '17 at 19:55
  • @Prisoner To make it work, I also had to use the full calendar scope name (instead of just using "calendar") in the Google Actions console. FYI. – Lizozom Jun 16 '17 at 08:18
  • 1
    @Lizozom - That is correct. The "profile" and "email" scopes are the full name of the scope in my examples. – Prisoner Jun 16 '17 at 09:41
  • @Prisoner - I'm still having trouble using the access token to authenticate with Calendar API. Maybe you could take a look at my question? Thanks! https://stackoverflow.com/questions/44589700/google-actions-access-to-calendar-api-with-access-token-fails – Lizozom Jun 16 '17 at 12:52
  • Google sign seems more difficult than it should be. I did as you have suggested in this answer but I get no change at all. Should I be expecting a popup asking for sign in when the user opens the action for the first time? In my welcome intent, I logged the value of `app.getUser().accessToken` but it's always undefined. – Pav Sidhu Aug 20 '17 at 14:21
  • @Prisoner , actually this will be last process after implementing the `Implict flow` or `Authorisation Flow` , can you able to configure any of the? or else am i missing something critical here? – Krsna Kishore Sep 25 '17 at 15:23
  • @PavSidhu - yes, you should be prompted to link the accounts. If you're not, you may want to open a question that describes exactly what you've done (showing sample code if necessary) and what it is or isn't doing. – Prisoner Sep 25 '17 at 15:26
  • @Webruster - I'm not sure I understand what you mean by "this will be last process" and what configuration you're talking about. If you've tried this and you're still having problems, can you post a new question with details, showing what your'e doing, and what didn't work? – Prisoner Sep 25 '17 at 15:27
  • @Prisoner first of all sorry for not being clear , i have already created a new Question https://stackoverflow.com/questions/46408690/unable-to-authenticate-users-using-implicit-flow-in-google-actions – Krsna Kishore Sep 25 '17 at 15:30
  • @Prisoner this is so clear and so super helpful. I followed the steps in this answer and it worked. – Damon Oct 24 '17 at 03:33
  • @Prisoner - I get this when I enter the authorization url "Google accounts cannot be used as Auth endpoint urls per our Account Linking policy " and I am not able to save the information. Is this something new? – dcinadr Oct 25 '17 at 22:25
  • 5
    Apparently they re-updated the policy on either October 4th or 7th to disallow this again. For a while their policy allowed it, and they didn't check for it, however the policy at https://developers.google.com/actions/policies/general-policies#account_linking now states "When implementing account linking using OAuth, you must own your OAuth endpoint" – Prisoner Oct 25 '17 at 22:53
  • @Prisoner I tried to link my Google Assistant App with my own Web Server with Google-OAuth2 but I'm always getting the same error I've describe my issue here. It would be great if you can help! [“Accounts failed to link” error happens when I try to authorize Google Assistant at my Web service](https://stackoverflow.com/questions/48461569/accounts-failed-to-link-error-happens-when-i-try-to-authorize-google-assistant) – Eugene Kovalev Jan 26 '18 at 12:53
  • I was already researching an answer for you. {: No need to page me from elsewhere. – Prisoner Jan 26 '18 at 13:01
  • 1
    You can bypass the point where you can't use google's OAuth server, Just see my answer below this post for further details. `Enter the auth uri as https://www.googleapis.com/auth . Save and run, It will show an error while running on the google assistant, but dont worry, Come back and enter auth_uri as https://accounts.google.com/o/oauth2/auth and token_uri as https://accounts.google.com/o/oauth2/token . Put the scopes as https://www.googleapis.com/auth/userinfo.profile and https://www.googleapis.com/auth/userinfo.email and weare good to go. Save the changes.` – Jatin Mahajan Apr 19 '18 at 07:23
  • "Google accounts cannot be used as Auth endpoint urls per our Account Linking policy" ?? – jtlz2 Jun 12 '18 at 06:50
  • @jtlz2 - What is the question? (Although this answer needs updating again.) – Prisoner Jun 12 '18 at 10:01
  • What is the difference between AuthorizationToken & Token Url? And how it is used. – vs_lala Jun 12 '18 at 15:02
4

After contacting Google the current situation seems to be that you should set up your own OAuth2 server, and then on the login screen of your OAuth2 server you should start the Google OAuth2 flow.

you have to have your own endpoint with Google Oauth2 - it is correct that you can't use Google Oauth itself as a provider. To use the Google OAuth service, you can use a "sign in with Google" button in your own endpoint instead.

Source: Contacting Google Actions on Google Support

Kind of speechless right now... as this seems to be a huge oversight on Google's part.

David Mulder
  • 26,123
  • 9
  • 51
  • 114
  • @Webruster Got irritated by the project (it was a private project) and never finished it. Sorry. – David Mulder Sep 25 '17 at 14:53
  • same feeling here – Krsna Kishore Sep 25 '17 at 14:56
  • You can bypass the point where you can't use google's OAuth server, Just see my answer below this post for further details. `Enter the auth uri as https://www.googleapis.com/auth . Save and run, It will show an error while running on the google assistant, but dont worry, Come back and enter auth_uri as https://accounts.google.com/o/oauth2/auth and token_uri as https://accounts.google.com/o/oauth2/token . Put the scopes as https://www.googleapis.com/auth/userinfo.profile and https://www.googleapis.com/auth/userinfo.email and weare good to go. Save the changes.` – Jatin Mahajan Apr 19 '18 at 07:20
  • 1
    Jatin - Have you published your app. It works great in test environment, but when published in production, it does not work. My app was turned down by google after it got published with this comment: "You must own your OAuth URL - it can not be owned by an external party." – Rajesh May 23 '18 at 10:39
2

I am able to make it work after a long time. We have to enable the webhook first and we can see how to enable the webhook in the dialog flow fulfillment docs If we are going to use Google Assistant, then we have to enable the Google Assistant Integration in the integrations first. Then follow the steps mentioned below for the Account Linking in actions on google:-

  1. Go to google cloud console -> APIsand Services -> Credentials -> OAuth 2.0 client IDs -> Web client -> Note the client ID, client secret from there -> Download JSON - from json note down the project id, auth_uri, token_uri -> Authorised Redirect URIs -> White list our app's URL -> in this URL fixed part is https://oauth-redirect.googleusercontent.com/r/ and append the project id in the URL -> Save the changes

  2. Actions on Google -> Account linking setup 1. Grant type = Authorisation code 2. Client info 1. Fill up client id,client secrtet, auth_uri, token_uri 2. Enter the auth uri as https://www.googleapis.com/auth and token_uri as https://www.googleapis.com/token 3. Save and run 4. It will show an error while running on the google assistant, but dont worry 5. Come back to the account linking section in the assistant settings and enter auth_uri as https://accounts.google.com/o/oauth2/auth and token_uri as https://accounts.google.com/o/oauth2/token 6. Put the scopes as https://www.googleapis.com/auth/userinfo.profile and https://www.googleapis.com/auth/userinfo.email and weare good to go. 7. Save the changes.

  3. In the hosting server logs, we can see the access token value and through access token, we can get the details regarding the email address.

  4. Append the access token to this link "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" and we can get the required details in the resulting json page.
  5. accessToken = req.get("originalRequest").get("data").get("user").get("accessToken")
    r = requests.get(link) print("Email Id= " + r.json()["email"]) print("Name= " + r.json()["name"])
Jatin Mahajan
  • 149
  • 1
  • 8
  • Link-only Answers are not good answers. While your link may provide the correct answer, it is still better to post the relevant part here and put the link as a reference. This is because your link might not be valid in the future anymore and when someone finds this answer he will not be able to get any value from it. – Absent Apr 05 '18 at 11:13
  • I got it and I edited my answer. I am new to posting answers on stackoverflow. Kindly help me grow. Thankyou :) – Jatin Mahajan Apr 05 '18 at 12:15
  • Really helpful answer, i was trying to do my actions-on-google authentication using Okta and while adding google as an identity provider but that seemed to never work smoothly with auto account creation on okta. – Ryan Zakariudakis Apr 14 '18 at 19:06
  • I'm glad that you found it helpful – Jatin Mahajan Apr 15 '18 at 11:40
  • "Generic URLs (such as example.com) are not allowed. You must provide a valid token url specific to your Action." – jtlz2 Jun 12 '18 at 06:53
  • Where should I redirect on fail login? – vs_lala Jun 19 '18 at 14:24
  • you dont have to redirect it . Just enter the correct auth and token URi and it'll work ` https://accounts.google.com/o/oauth2/auth https://accounts.google.com/o/oauth2/token` – Jatin Mahajan Jun 25 '18 at 09:09
1

You need to implement the Oauth protocol with whatever Google Assistant app you are developing. Let me be a bit more clear:

  1. The user is on the assistant, you need to link him to any data you have on your App side
  2. The access to the data you have about your user is protected by an access token
  3. Google then needs to ask you for this token to have access to this resource
  4. When google has the token it can send it to the app so it validates every requests to get the resource.

This is why you need to implement your own oauth server (Honestly it is just two more endpoints in your application): the identity is checked on google's side, but the link between the user and the resource to access can only be known by you. The process above is valid, you just need to specify your own token endpoint and your own auth endpoint. Note that if you only want to check that the user is logged in into google and get his email, you just need to implement the streamlined identity flow that does not require the /auth endpoint (Automatically Sign Up Users with Streamlined Identity Flows)

That beeing said I implemented the flow but get the same error : expected_inputs[0].possible_intents[0]: Transactions/Identity API must be enabled before using.

Prags
  • 2,457
  • 2
  • 21
  • 38