So, you want to access data from a Google user in your application. To accomplish this the user must allow your application to operate as the user. Although it looks simple by clicking “accept” on the login prompt there is a lot more going on than just that. Of course Google has documentation about how this authorization works, but it gets complicated when they start talking about refresh tokens, access tokens, expiration time, client secret, etc.
First things first, let’s start with looking at a Google account. Google has a lot of different services.
When you create a Google account you are automatically can use your account for Gmail, Chrome, Youtube, Google Maps, Google Play and Google+. Eventually you can make use of other Google services by just signing in with your Google account.
To set up a project, follow the next steps:
Keep the following things in mind:
- We want to access data from a unknown user
- We are building a web application
- Create a developer account at https://console.developers.google.com/
- Login with your developer account at https://console.developers.google.com/
- Click "Create Project"
- Fill in your project name
.
Optional: below “”Show advanced options” you can choose where the project will run. Either in the US or Europe - Click "Create".
Google will now create your project this will take a minute. - In the left menu select “APIs & auth” > “Consent screen”
The consent screen is the authentication prompt for the user when it wants to use your application. - Select for email address your developer account and fill in a product name. All other fields are optional.
- Click "Save".
- Select in the left menu “APIs & auth” > “APIs”
Here you can add APIs to your project to access different google services. - Select or search for an API you want to use.
- Click "Enable API",
- Select in the left menu “APIs & auth” > “Credentials”
Here you will create the authentication tokens for your application. - Click "Create new Client ID".
- Select “Web application”.
- At “Authorized JavaScript origins” fill in the host address of your web application. This can only be one URL.
- At “Authorized redirect URIs” fill in the URL path where you want to handle the authentication.
- Click "Create Client ID"
What happened now is that we create credentials for our application to access the API project.
With the Client ID and Client Secret your application can connect to your Google Project
At this point it is useless since there are no users that have authorized your application to access their data.
oAuth Flow
The next step is to make it possible for users to authorize your application to access their data. This is where the oAuth2.0 flow will kick in.
The flow exists of 2 steps:
- Generate the login URL
- Exchange login code
Step 1: generate the login URL
The user must login to your application. Therefor you must use a specific URL for the user to login. Google oAuth has its own structure for it. The endpoint for a Google login is https://accounts.google.com/o/oauth2/auth
The URL itself is not enough. It will require some parameters. All parameters can be found at https://developers.google.com/identity/protocols/OAuth2WebServer#formingtheurl
For your web application it is sufficient to use the following parameters:
redirect_uri
: The URL where the user will be redirected to after he signed in. This URL must be registered in your Google Project in your Google developers console. If this is not the case your will get an error “redirect_uri_mismatch”response_type
: Determines if Google Oauth will return a code. Web application must use this option.client_id
: The Client ID that is generated for your web application in the Google developers console.scope
: Determines for what API your application wants access to. For a full list of scopes visit https://developers.google.com/oauthplayground/ Note: Adwords is not in the list. The adwords scope is https://www.googleapis.com/auth/adwordsapproval_prompt
: Indicates if the user should always accept your application before continuing.access_type
: Indicates if the application wants to access the user’s account if the user is logged in or not.
For example here below you will see an authentication URL to allow my web application to read out all of the Google analytics data and email address from a user. For my web application I also want to access his data even when the user isn’t online.
Note: Remember to add Google analytics as an API to your project
Example URL with breaklines for readability:
https://accounts.google.com/o/oauth2/auth?
redirect_uri=http://www.mywebapp.com/oauth2callback&
response_type=code&
client_id=104608secret-secret-secret-secret.apps.googleusercontent.com&
scope=https://www.googleapis.com/auth/analytics.readonly+https://www.googleapis.com/auth/userinfo.email&
approval_prompt=force&
access_type=offline
When visiting the URL the user first have to login with his Google account. When the user is logged in the user will see your consent screen (in out case, it is in Dutch).
When the user clicks on “Accept” google will redirect the user to your given redirect_url with a code in the GET. The URL will look like this:
http://www.mywebapp.com/oauth2callback?code=4/gXCN77EWLDCOfakep2tvfakezOg6Mn0fakej2vA.giyP3fakejxeAeYFZr95uygvU3j0dumQI
Step 2 Exchange login code
In your application you must get the code from the request. The next step is to send a POST request to the Google server to retrieve the credentials of the user and verify that your application can access the user’s data.
The POST request must contain the following parameters
Code
: The authorization code from the GET requestClient_id
: The Client ID that is generated for your web application in the Google developers console.Client_secret
: The client secret that is generated for your web application in the Google developers console.Redirect_uri
: The URL where the user will be redirected to after he signed in. This URL must be registered in your Google Project in your Goolge developers console.Grant_type
: Identifies the type of token returned. For this example the value is always authorization_code
The POST address should be https://accounts.google.com/o/oauth2/token and also will need a header with Content-Type: application/x-www-form-urlencoded
A POST request will look like as followed:
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
code=4/gXCN77EWLDCO_fake_p2tvfakezOg6Mn0fakej2vA.giyP3fakejxeAeYFZr95uygvU3j0dumQI&
client_id=104608secret-secret-secret-secret.apps.googleusercontent.com&
client_secret=90V0FAKE_WkFAKExrHCZti&
redirect_uri=http://www.mywebapp.com/oauth2callback&
grant_type=authorization_code
The response of the request will return a JSON array. The JSON array will contain the following fields.
Access_token
: The token that will grant you access to user accountRefresh_token
: A token that can be used to obtain a new access token. This field is only present if access_type=offline is include in the authorization code request.Expires_in
: The remaining lifetime of the access token in secondsToken_type
: Identifies the type of token returned. In this example it always will have the value BearerId_token
: Will contain the user’s account information. Will only be present if your application wants to know information about the user. Depends on the scope|
The example request will return something like this:
{
“access_token”:”1/fjfKDe9irjnfAJDFkjFDKjreoijf”,
“expires_in”: 3920,
“token_type”: “Bearer”
“refresh_token”:”4/NdkereoIjnrOIKJMNFI39KEJRNF”
“id_token”: {“email”:”googletest@bluemango.nl”}
}
Your application is now ready to access the data from the user. When you try to connect to a API you always have to pass the oAuth 2 credentials to the API. The user can go to https://myaccount.google.com and login. The user can scroll down to “Connected apps and services” and click on “Account permissions”.
The user can now see a list of apps that are allowed to access his data. By selecting a app and clicks in the right panel on "Revoke access" the user will disable the app to access his data. Now that we have logged in and gained access to the user its data we now have the following completed.
The access token will allow your application to access data from the user.
Tokens
So now that we can access the users data let’s take a look at the different tokens that came by and what they mean.
Basically we need an access_token to access the user data. The downside of an access_token is that it will expire after about one hour. This means that storing the access_token is useless. You will only use the access_token for a one time session. To solve this problem Google created the refresh_token. This token allows you to generate a new access_token for your application. This allows your application to create a new session to access the user data at any time.
To retrieve the refresh_token you have to include access_type=offline in the authorization request in step 1 of the Oauth2 flow. The refresh_token will only be generated at the first time the user accepts your application to access your data. If a user already accepted your application and will come back another time and accepts your application again. The refresh_token is not generated. The user must first revoke your application. After the user has revoked your application and then logs in and accepts your application, a new refresh_token is generated.
It is also possible to revoke the application access by sending a GET request. The GET request must be send to https://accounts.google.com/o/oauth2/revoke with a token as parameter. This token can either be an refresh_token or access_token.
Example:
https://accounts.google.com/o/oauth2/revoke?token=1/fjfKDe9irjnfAJDFkjFDKjreoijf
By executing the request it will revoke the application from the user where the token belongs to.
Generating tokens
A access_token or refresh_token are specifically generated for your application. This means that you can’t use these tokens to access a user account with another application or for different services. That means if you add new APIs to your application the user must reaccept your application.
So what is the best workaround with these tokens?
The refresh_token with the correct client_id and client_secret will allow other people to use your application to access services of an user account. Some Google APIs allows you to programmatically add or delete stuff from a user. The first thing to prevent this is that you must consider what you want to do with the account. Like for Google analytics when you only want to retrieve data you should use https://www.googleapis.com/auth/analytics.readonly as scope, just in case your parameters are leaked, other people can only retrieve Google analytics data.
Second thing is that you store your client_id and client_secret on different locations than your source code. Also do not store them at the same place as the retrieved refresh_tokens.
The third thing you should do is to reset your client_secret once a while. This can be done in the developer console at the credential area.
Leave a Reply
You must be logged in to post a comment.