Integration of Google Drive into Force.com

Google Drive is a file storage and synchronization service by Google    that was released on April 24, 2012. Rumors about Google Drive began circulating as early as March 2006. Unlike the other online storage services, the main feature that attracts one to the Google Drive is the Google Docs app. When a file is uploaded to the Google Drive, one can actually see the file contents via the Google Docs viewer without actually downloading it to your local machine. Thus, the files maintain their format identity when they reside on the Google Drive and do not become a mere data.

Google Drive gives all users 5 GB of cloud storage to start with and one can experiment with this free storage. Users need not sign in for another account to activate Google Drive. All the users who have a Gmail ID will also have access to their bucket of space on the Google Drive.

The first and foremost thing that you must have is a Gmail ID. I think that statement will not have any relevance today, as most of us have it and we usually sign in for Facebook with the Gmail IDs. Well, now you should create an API Project. In order to create the same, visithttps://code.google.com/apis/console/. If you haven’t created one, the first thing that it will ask you is to create one. If that is done, go to the Services tab (I think it’s the one that opens automatically after the creation of a project) and you will be able to see a bunch of Google Services. In that list, switch the Drive API service to ‘ON’. The other best thing is that we have a limit of 500,000 requests per day which is really helpful. Three cheers to Google!!

As Google Drive comes as a part of your Gmail Account, it is obvious that we have to log in with our credentials before we can actually upload, download or view the files that reside in Google Drive bucket. Now, this can be handled by either of the following two ways. We can handover our credentials i.e., our password and our user id to the third party application which will be accessing the resources. This is certainly not a good idea. The second alternative is where the concept of OAuth 2.0 comes into play. OAuth 2.0 allows users to share specific data with any other third party apps (for example, contact lists) while keeping their usernames, passwords, and other information private.

If that’s clear and if you really don’t want to disclose your master password to any third party app, let’s get into some basics of OAuth 2.0 since our Salesforce App will be accessing the Google Drive via the OAuth tokens. Go to the API Access tab which is below the Services link and click on Create an OAuth 2.0 client ID….       This will open to a wizard with two screens where we have to enter the details about the application that is going to access our Google Drive bucket via our Gmail Account. In our case, it will be the app that we have created on the Force.com platform. Let’s fill up the Product name with say ‘HRForce’ and then click next. On the Step 2 of 2, select the Application Type as Web Application. For time being, let’s just skip the other details and proceed with ‘Create Client ID’. You can see that the Client ID and the Client Secret are created. We can also notice that two fields, Redirect URIs and JavaScript origins aren’t set with any values. Don’t worry; let’s forget about them for time sake and I assure I will get to it soon.

The next thing we are going to do is to understand how actually we can use the OAuth 2.0 tokens to authorize the desired account and to access the APIs. The best place to learn this is the ‘OAuth 2.0 Playground’. Don’t hesitate, it is not a developer manual or API reference, it’s just a playground. You can reach the same at https://developers.google.com/oauthplayground/. In the Step 1, select the API that you wish to Authorize. Let’s selecthttps://www.googleapis.com/auth/drive and click on Authorize APIs. The page will be redirected to the Gmail’s login page(provided that you are not loggend in). Then, fill in your Gmail credentials and click Sign In. If the Sign In was successful, a new page is displayed which asks the account holder whether to allow access for the 3rd party app (Google OAuth 2.0 Playground) or not. No doubt, we have to allow and don’t panic, it’s not going to steal anything from your Google Drive bucket. But before that I would like you to peek at the URL.

https://accounts.google.com/o/oauth2/auth1?scope=https://www.googleapis.com/auth/drive2&response_type=code3&access_type=offline4&redirect_uri=https://developers.google.com/oauthplayground5&approval_prompt=force6&client_id=407408718192.apps.googleusercontent.com7&hl=en&from_login=1&as=-7352876500034384

1This is the URL to which we have to direct to from our Salesforce app in order to get a grant for access from the user. Now, this is done only for the first time and we need not do it every time when we access Google Drive.

2Scope(s) are those Google APIs that the app wants to access.

3Response Type with a value code indicates that Google should give me an Authorization Code in return after the approval process has been completed successfully.

4Access Type with a value offline is used if your application needs to refresh access tokens when the user is not present at the browser. This will result in your application obtaining a refresh token the first time your application exchanges an authorization code. Now, I am pretty sure that you will be confused with terms access token and refresh token. We will look into soon.

5Redirect Uri determines where the response is sent. The value of this parameter must exactly match one of the values registered in the APIs Console (including the http or https schemes, case, and trailing ‘/’). Yes, this something which we had actually skipped in that two-step wizard which involved the creation of the OAuth 2.0 Client ID. In our case we can actually configure this URL only if we are ready on the Salesforce side. Google redirects to this URL after a successful approval with the Authorization Code as a parameter in the Query String.

6Approval Prompt indicates if the user should be re-prompted for consent. If the value is force, then the user sees a consent page even if they have previously given consent to your application for a given set of scopes.

7Client ID is the one that we had created on the Google APIs Console while creating the OAuth 2.0 Client id.

Well, now let’s click Allow Access. You can observe that we are redirected back to our OAuth 2.0 Playground’s home screen. Look at the URL and you can notice that we have a parameter named code with a value. This value is the Authorization Code. This Authorization Code is then exchanged in order to receive an access token and a refresh token. Click on the Exchange authorization code for tokens. Both the Refresh Token and the Access Token will be fetched.

Access Token plays the role of the passwords. We can use the Access Token as a substitute for passwords in order to prove the identity and then access the Google API. These Access Tokens have a lifetime of 3600 seconds or 1 hour. Any access to the Google APIs with an expired access token will be denied. There comes the role of Refresh Tokens. The Refresh Tokens never expire and they can be used to retrieve new Access Tokens.

The most important thing that we have to keep in mind is that, on clicking the Exchange authorization code for tokens, a POST request is made. On the right hand side pane of the Playground, we can see that a POST has been made to /o/oauth2/token with host being accounts.google.com. In other words, a POST request is being made to https://accounts.google.com/o/oauth2/token with a message body containing information as below:

code=4%2FpnlSoZoIp0trg04KIW8gAFC6r099.kgQZqaF3M6kSgrKXntQAax0o1-_gdgI&redirect_uri=https%3A%2F%2Fdevelopers.google.com%2Foauthplayground&client_id=407408718192.apps.googleusercontent.com&scope=&client_secret=************&grant_type=authorization_code

The code parameter contains the Authorization Code and grant_type parameter has a value authorization_code. The response to this POST request is a JSON text containing the Access Token and the Refresh Token.

{
   "access_token":"ya29.AHES6ZQ1njBd9EMusvihjSxjZ_Z-JPLLqBDExAI3_IeTHLYQKzyZtw",
   "token_type":"Bearer",
   "expires_in":3600,
   "refresh_token":"1/fBbyP9Slezg3oibr5BdpkpgDrmVXS-op4y19fIzy4js"
}

If we want to refresh our expired Access Token, then we must make a POST request to the https://accounts.google.com/o/oauth2/token but with a different message body. The message body will contain the client_id and client_secret and will no longer have the code parameter. Instead of theredirect_uri parameter we will have a new parameter named refresh_token with the refresh token value and the grant_type will not haveauthorization_code as the value and rather it will take refresh_token as the value.

Thus we have received an Authorization Code, an Access Token and a Refresh Token from Google. Now, let’s move to the Force.com Platform. At first, as per the best practices, I suggest that we should create a Custom Settings which will keep the tokens. Let’s name it KeySafe. The entries in the KeySafe may include the Client ID, Client Secret, Authorization Code, Access Token and the Refresh Token. Also, we will maintain an another Custom Settings named Enpoint which will keep the different endpoints like the Scopes, Redirect URL, Authentication URL, Tokens URL and so on.

Endpoint Custom Settings

ENDPOINT CUSTOM SETTINGS

Key Safe Custom Settings

KEY SAFE CUSTOM SETTINGS

Now, we can write an Apex Class which will make the POST requests for getting the Access Token, Refresh Token and also make requests for new Access Tokens with a Refresh Token.

public class GoogleDrive
{
 private static Http http;
 private static HttpRequest httpReq;
 private static HttpResponse httpRes;
 private static void Initialize()
 {
  http = new Http ();
  httpReq = new HttpRequest();
  httpRes = new HttpResponse();
 }
 public static boolean getTokens(String tokenType)
 {
  String messageBody='';
  Initialize();
  httpReq.setMethod('POST');
  httpReq.setEndpoint(<Fetch the Google Token URL from EndPoint>);
  httpReq.setHeader('content-type', 
   'application/x-www-form-urlencoded');

  messageBody = 
  'client_id='+<Fetch Client ID from Key Safe>+ 
  '&client_secret='+<Fetch Client Secret from Key Safe>;

  if(tokenType=='ALL')
   messageBody = messageBody + 
   '&code='+<Fetch Authorization Code from Key Safe>+ 
   '&redirect_uri='+<Fetch Redirect URI from EndPoint>+ 
   '&grant_type='+'authorization_code';

  else if(tokenType=='ACCESS_TOKEN')
   messageBody = messageBody + 
   '&refresh_token='+<Fetch Refresh Token from Key Safe>+ 
   '&grant_type='+'refresh_token';

  httpReq.setHeader('Content-length', 
    String.valueOf(messageBody.length()));

  httpReq.setBody(messageBody);
  try
  {
   httpRes = http.send(httpReq);
   parseJSON(httpRes.getBody());
   return true;
  }
  catch(Exception ex)
  {
   System.debug('ClassogleDrive', 
   'Method: getTokens', 
   ex.getMessage());
   return false;
  }
 }    
 private static void parseJSON(String jsonText)
 {
  JSONParser parser = null;
  parser = JSON.createParser(jsonText);
  while (parser.nextToken() != null)
  {
   if(parser.getText()=='access_token')
   {
    parser.nextToken();
    <Save as Access Token into Key Safe>
   }
   if(parser.getText()=='refresh_token')
   {
    parser.nextToken();
    <Save as Refresh Token into Key Safe>
   }            
  }    
 }

Now, a question that can arise is what is Redirect URI and where should we set a value for the same. It’s quite certain that you will be having a doubt about the same as we had skipped that portion of setting the Redirect URIs and JavaScript origins in that two step wizard that we had come across while creating the API Project. In the implementation that I had done, I had made a Tab on the Force.com Platform called the Authentication which had two buttons namely, the ‘Authorize’ and ‘Get Tokens’.

Authentication Tab

AUTHENTICATION TAB

When user clicks the Authorize button, the page is redirected to Google’s Login Page initially (provided that you have not logged in) and followed by Allow Access page. Once we click the Allow Access page, we will be redirected back to our Authentication tab with an additional Authorization Code in the Query String. We were redirected back because I had set my Redirect URI at the Google API Console to the address of my Authentication tab.

Now, when the user clicks the Get Tokens button, a server side POST is made with the Authorization Code that we received from the above step along with the other parameters which include the Client IDClient SecretGrant TypeRedirect URI and the Refresh Token. Now, don’t get confused. If you look at the Apex Class(written above) the parameters for getting a Refresh Token and Access Token varies. Both the Client ID and Client Secret are required regardless of whether we need an Access Token or a Refresh Token. Even though server side POSTs does not do any redirection, Google requires us to set the value for Redirect URI which is the same as that you had set from API Console.

Now, the last thing that is left to say is how can we upload a file to the Google Drive by authenticating ourselves using the Access Token that we have received. To do this, I had created a VisualForce page named Documents Uploader 

Documents Uploader Page

DOCUMENTS UPLOADER PAGE

with following script tag :

<script type="text/javascript" src="https://apis.google.com/js/client.js"/>

Once we get the file from the user call the,

request = gapi.client.request( 
{ 
 'path'    : <The Path of the Shared Folder on Google Drive>,
 'method'  : 'POST', 
 'params'  : {'uploadType': 'multipart'}, 
 'headers' : 
  { 
   'Content-Type'  : 'multipart/mixed; boundary="' + <Boundary Seperator> + '"',
   'Authorization' : 'OAuth ' + <Fetch the Access Token from Key Safe>  },
 'body'    : <File Contents seperated by the Boundary Seperator> 
});

request.execute(<Name of Callback Function>);

In fact I had used the same script the was provided by Quickstart(https://developers.google.com/drive/quickstart-js) tutorial published by Google. The only addition that I had to add was the ‘OAuth ” term along with the Access Token in the Authorization header which otherwise Google has done using theAuthorize(…) method. The Authorize(…) method provides us with an Access Token and when we use the Authorize(…) its not required by us to mention this additional Authorization header. The problem of using the Authorize(…) method is that it requires a User Grant every time after the Access Token expires which is not all User Friendly approach.

That’s it. We are done. I hope you would have had a brief understanding of the whole stuff. I know that a visual presentation of whole stuff can definitely bring the topic much closer to you. I hope I can come up with a recording demoing the whole stuff so that you can get a clear picture of how things really goes about. Also, you are welcome to post your ideas and views about this article. Do approach me for doubts or clarifications.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值