How to send regular protected requests using Google sign in? - google-oauth

I am trying to integrate the Google sign in sdk into my site.
I have already added the GSI button to my site and on clicking it, google sends the IDtoken containing the user info to my oauth endpoint.
Using this token, I can now create a new user account.
So far so good.But I am not sure what I am to do from here.
Should I put this IDtoken into a http_only and secure, cookie so that all authz server requests will contain the userid?
I am seeing lots of cookie and local storage based data has been been added to my sites jar. Am I supposed to use them in any way?
What do I need to do after the token expires after 1 hr? Do I need to have my users login yet again? I did not get any refresh token along with the idtoken. Do I even need to handle the refresh token or is the gsi sdk supposed to take care of all that for me?
Another part which is not clear is what do I get from using the Google sign in button/sdk vs the general Oauth-openid flow.

Related

How to authenticate user with just a Google account on Actions on Google?

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.
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:
Configure your project (in the cloud console) so that the Calendar API is enabled and that the OAuth2 client is correctly configured.
Configure the Action for account linking in the action console.
Configure the Actions on Google Integration for your API.AI Agent to indicate that sign-in is required.
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.
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.
Select the "Credentials" menu on the left. You should see something like this:
Select "Create credentials" and then "OAuth client ID"
Select that this is for a "Web application" (it is... kinda...)
Enter a name. In the screen shot below, I used "Action client" so I remember that this is actually for Actions on Google.
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:
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.
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).
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.
Go to https://console.actions.google.com/ and select the project you'll be working with.
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.
Select the Grant Type of "Authorization Code" and click Next.
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.)
For the Authorization URL, enter https://accounts.google.com/o/oauth2/v2/auth
For the Token URL, enter https://www.googleapis.com/oauth2/v4/token
Click Next
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.
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.
Go to https://console.api.ai/ and select the project you're working with.
Select "Integrations" and then "Actions on Google". Turn it on if you haven't already.
Click the "Sign in required for welcome intent" checkbox.
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.
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.
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:-
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
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.
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.
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.
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"])
You need to implement the Oauth protocol with whatever Google Assistant app you are developing. Let me be a bit more clear:
The user is on the assistant, you need to link him to any data
you have on your App side
The access to the data you have about
your user is protected by an access token
Google then needs to
ask you for this token to have access to this resource
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.

Generate Permanent Instagram Access Token

We have an Instagram client id and client secret, and already have gone through the documentation of generating access tokens which requires redirect url.
Note that we also have disabled the implicit OAuth flow.
Now we already have generated the access token using URL below (for authenticated user, it returns the access token appended in the response URL)
https://api.instagram.com/oauth/authorize/?client_id={client_Id}&redirect_uri={redirect_url}&response_type=token&scope=public_content
Can this token be stored in the database / configuration files and re-used for any new Instagram API requests? e.g.
https://api.instagram.com/v1/users/{user_id}/media/recent/?access_token={reusable_access_token}
Based on the official documentation, we understand that the access token can become invalid at any point of time, we would like to know if there are any specific scenarios which leads to invalidation of the access token?
What would be the best way to generate token once and use it for each API request? We definitely do not want users to enter credentials manually to generate tokens.
Unfortunately at that point it's not possible:/ Instagram doesn't provide refreshing access token in the background.
User needs to login with their credentials, so you can obtain new access token. Some kind of workaround (not nice, but it's working) is to watch for error type OAuthAccessTokenException and notify the user via e-mail about such fact. He will have to login once more, so you can get fresh and working access token.
Also, please keep in mind that access tokens has a pretty long life span. It doesn't expire after a day or two, unless Instagram API has some issues (like just now OAuth - unable to exchange code to access token for some users).
Otherwise it works really well.
However it would be super nice if Instagram could add to their API renewal option in the background for access tokens for users that autorised your app, but their token expired:)

Mobile to backend authentication

I am trying to implement a login for my mobile app to my backend. I previously used to use a method that required hashing on mobile site and backend site. The password would be hashed saved on the mobile site and be included in the hash. If hashes on mobile side and backend side would be equal, the request would be valid.
However I wanted to add Facebook login to my login system so I kinda find out it was not gonna work the way I had built it before. I came to the conclusion that I probably have to change the entire method to token login.
What I have currently functioning is Facebook button on mobile side, this creates for me a Facebook userid and Facebook access token. I send both these values to my backend and use a Facebook graph call to retrieve the facebookid from the access token. if both the Facebook userids are equal. I either register the user or log him in.
This is where I get stuck. I now want to generate my own token to send back to the mobile side, because I have custom login (email+password) (Facebook is just an option). So I think using my own auth token for both ways is the best.
I have a few questions about this token:
What should the token exist of?
Do I need to save this token on the mobile (not hashed?)
What is the best way to built in expiring time and automatic refresh token
What I can't really understand is the security of this authentication method. Sending a token over a request that gives you access to user information is just as bad as a plain password I think? Is SSL connection simply enough?
I understand these are a lot of question in one but I hope someone can give me a clear explanation.
Thank you
You can try JWT (JSON web token), it's really simple. The idea its, when you do the login, the servers return you the JWT and you simply have to save it in your mobile app. Then you have to pass it as a header (assuming you are developing for Android):
request = new HttpGet();
request.addHeader("Authorization", "Bearer " + Global.loginData.jwt);

OAuth v2 (Google API) expiry Access Token

I am building an integration component using a graphical framework who has a pre-build OAuth2 connector.
This framework required following fields for OAuth v2:
Grant type
Scope
Auth Server URL
Client Id
Client Secret
Access Token
Refresh token
I need to get data from Google Analytics API, so I went to Google Dev Console
(https://console.developers.google.com/project/927890000889/apiui/credential). I generated a 'Client ID for web application'. From the parameter of this object I was able to fill some of the parameters above
Grant type : 'authorisation_code'
Client Id : 'RANDOMCHARSam5o37nsiu730d.apps.googleusercontent.com'
Client Secret : 'RANDOMCHARSiSwBA5OH5qYLUa'
Then using Google Oauth Playground (https://developers.google.com/oauthplayground) I was able to fill the missing bits
Scope : 'https://www.googleapis.com/oauth/analytics'
Auth Server URL : 'https://accounts.google.com/o/oauth2/auth'
Access Token : 'RANDOMCHARSQAQv4HRF5-JsQEzUS61lj2YremyCocv0PQ4-agpzJe'
Refresh token : 'RANDOMCHARSLPJnL4FPaDc2KP6V8kCzjjHO2Kj4Np_3X0'
Everything works fine, I am authorised to access and I get data from Google Analytics, but just for a while, after few minutes if I retry I receive an authorisation failure error.
I believe that the problem is related to the expiration of the Access Token, but I don't know how to solve that.
Worth to mention that this activity it's batch (no human interaction), so nobody can request a new access token.
The integration framework is not extensible (I cannot write code to renew the code) so I believe there's a way to get a access token that never expire or some other mechanism to achieve the same result.
Bottom line, I am not sure if I approached the requirement correctly since the beginning (Client ID for web application).
Any help is much appreciated,
Giovanni
Access tokens typically expire after 60 minutes. If you have a refresh token you can use the refresh token to get a new (valid) access token.
This doc explains how to do that:
https://developers.google.com/accounts/docs/OAuth2WebServer#refresh
To answer your overarching question, yes, you are approaching everything correctly. All you need to do is handle the case where the access token has expired by refreshing it. Also, when you originally requested the access token the response should tell you how long it's valid for, so you should only refresh that token if it's expired.
You can use Refresh tokens to make it more long used.
The Google Auth server issued Refresh tokens never expire,
A token might stop working for one of these reasons:
The user has revoked access.
The token has not been used for six months.
The user changed passwords and the token contains Gmail scopes.
The user account has exceeded a certain number of token requests. There is currently a limit of 50 refresh tokens per user account
per client.If the limit is reached, creating a new token automatically invalidates the oldest token without warning.
This limit does not apply to service accounts.
from: https://developers.google.com/identity/protocols/OAuth2

OAuth2 Authorization Code in Cookie, good or bad?

I can not seem to find a SIMPLE answer to the question on how to persist OAuth2 authentication... Let's take Google+ OAuth2 API as an example.
User goes to page
User is not authenticated, and gets redirected to authentication page where he logs in
User logs in successfully and authorises my app
User gets redirect to specified (by me) URI with Authorisation Code
I use authorisation code to obtain a token in order to submit queries in the name of the user
All is good and well. My question is: how do you SECURELY know at step 2 that the user visiting the page is already logged in, without having to go through the whole process of redirecting him to all these pages.
I assume storing the Authorisation Code retrieved at step 4 in a cookie is not an option.
All of this will happen in a server-side (Go - if that matters) application.
Any help is much appreciated... I need a simple solution.
Thank you!
use server-side sessions to store any authentication state or even access tokens if you need them.
one solution is to use a database for session store (an encrypted cookie holds the session id)
and another is to use cookie sessions (encrypted cookies that hold the session data).
using encrypted cookies that only the server is able to decrypt should be safe enough.