We have covered many points in lightning, but integration is the one we never touch. So today we will do Integration with google drive and upload File to Google Drive Using Lightning Component. Firstly we will do the Authentication with Google Drive. Once we get the Acces Token we will use that token to make request and upload File to Google Drive Using Lightning Component from Salesforce.
Firstly, we need to create oAuth app in google developer console. Sign in with your existing Google Account. Create a Project from the Home screen.

It will take a few minutes in project creation. Once the project was created open that project. And in the sidebar click on the “Credentials” tab and in the next screen click on the “CREATE CREDENTIALS” button and select OAuth Client ID.



Google might ask to configure the consent screen so once you did that. In the next screen, we will create an app. So give any suitable name and in Authorised redirect URLs, add our Salesforce page/tab URL. In this URL we will get the access token. So remember to enter exact URL else we will get URL mismatch error.



Now after the connected app is created. You will get the Client ID, Client Secret. So store them for future reference as we need them while making request. You can update the callback URL once we create a tab for our component.
Next, we need to create two Remote Site settings. Refer below URLs and add them in the Remote Site setting.



So now we have done with our configuration and we are ready to make our request. So to do that Just add the below code in your org.
oAuthGDrive.cmp
<aura:component controller="GoogleDriveController" implements="lightning:isUrlAddressable,force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<aura:attribute name="accessToken" type="String" />
<aura:attribute name="myRecordId" type="String" default="0016F0000XXXXXXXXX" description="This is the record where we will temproary store the file"/>
<lightning:card title="Google Drive Demo">
<lightning:button variant="brand" label="Google Drive Auth" title="Google Drive Auth" onclick="{! c.doAuth }" />
<hr/>
<p class="slds-p-horizontal_small">
<!--file upload part -->
<lightning:fileUpload label="upload file to Drive" name="fileUploader"
multiple="false" accept=".jpg, .png" recordId="{!v.myRecordId}" onuploadfinished="{!c.handleFilesChange}" />
</p>
</lightning:card>
</aura:component>
oAuthGDriveController.js
({
doInit : function(component, event, helper) {
if(component.get("v.pageReference") != undefined && component.get("v.pageReference") != 'undefined') {
var code = component.get("v.pageReference").state.code;
if(code != undefined) {
var action = component.get("c.getAccessToken");
action.setParams({
"code" : code
});
action.setCallback(this, function(response){
var status = response.getState();
if(status === "SUCCESS"){
var accessToken = response.getReturnValue();
component.set("v.accessToken", accessToken);
}
});
$A.enqueueAction(action);
}
}
},
doAuth : function(component, event, helper) {
var action = component.get("c.createAuthURL");
action.setCallback(this, function(response){
var status = response.getState();
if(status === "SUCCESS"){
var authUrl = response.getReturnValue();
window.location.href = response.getReturnValue();
//if you want to use standard method use below code. But it will open in new tab.
/* var urlEvent = $A.get("e.force:navigateToURL");
urlEvent.setParams({
"url": authUrl
});
urlEvent.fire();*/
}
});
$A.enqueueAction(action);
},
handleFilesChange : function(component, event, helper) {
var uploadedFiles = event.getParam("files");
var attachmentId = uploadedFiles[0].documentId;
var code = component.get("v.accessToken");
var action = component.get("c.uploadFile");
action.setParams({
"attachmentId": attachmentId,
"accessToken" : code
});
action.setCallback(this, function(response){
var status = response.getState();
if(status === "SUCCESS"){
var responseCode = response.getReturnValue();
if(responseCode == '200')
alert('File Uploaded successfully');
else
alert('There was some error');
}
});
$A.enqueueAction(action);
}
})
GoogleDriveController.apxc
public class GoogleDriveController
{
private static String key = 'XXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com';
private Static String secert = 'XXXXXXXXXXXXXXXXXXXXXXX';
private Static string redirect_uri = 'https://XXXXXXXXXXXXXXXXXXXXXXXX/lightning/n/GDrive_Demo';
@AuraEnabled
public static String createAuthURL() {
String key = EncodingUtil.urlEncode(key,'UTF-8');
String uri = EncodingUtil.urlEncode(redirect_uri,'UTF-8');
String authuri = '';
authuri = 'https://accounts.google.com/o/oauth2/auth?'+
'client_id='+key+
'&response_type=code'+
'&scope=https://www.googleapis.com/auth/drive'+
'&redirect_uri='+uri+
'&access_type=offline';
return authuri;
}
@AuraEnabled
public static String getAccessToken(String code)
{
//Getting access token from google
HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setEndpoint('https://accounts.google.com/o/oauth2/token');
req.setHeader('content-type', 'application/x-www-form-urlencoded');
String messageBody = 'code='+code+'&client_id='+key+'&client_secret='+secert+'&redirect_uri='+redirect_uri+'&grant_type=authorization_code';
req.setHeader('Content-length', String.valueOf(messageBody.length()));
req.setBody(messageBody);
req.setTimeout(60*1000);
Http h = new Http();
String resp;
HttpResponse res = h.send(req);
resp = res.getBody();
Map<String,object> responseMap =(Map<String,object>)JSON.deserializeUntyped(res.getBody()) ;
String token = String.valueOf(responseMap.get('access_token'));
return token;
}
@AuraEnabled
public static String uploadFile(String attachmentId, String accessToken) {
List<ContentVersion> cvFile = [SELECT VersionData,FileType,ContentDocumentId FROM ContentVersion WHERE ContentDocumentId =: attachmentId];
Blob myBlob = cvFile[0].VersionData;
String url = 'https://www.googleapis.com/upload/drive/v2/files?uploadType=media';
string authorizationHeader = 'Bearer ' + accessToken;
Integer contentSize = myBlob.size();
HttpRequest req = new HttpRequest();
req.setheader('Authorization',authorizationHeader);
req.setheader('Content-Length',String.valueOf(contentSize));
req.setheader('Content-Type','image/'+cvFile[0].FileType);
req.setMethod('POST');
req.setEndpoint(url);
req.setBodyAsBlob(myBlob);
Http h = new Http();
Httpresponse resp = h.send(req);
//After file was successfully upload we delete the file
delete new ContentDocument(Id = cvFile[0].ContentDocumentId);
return String.valueOf(resp.getStatuscode());
}
}
Here we are using lightning:fileUpload
to upload the file on google drive. In the doAuth
method we are doing redirect to get code and using this code we will make another request to get Access token. Once we get the Acess token we will make another request to upload file to Google drive. Here we need to take care of Salesforce governor limit so we cannot use a large file.
Finally below is how our flow will run.



Do you like the post or want to add anything. Let me know in the comments section.
Check my updated post to Use Named Credentials for Authentication and Solve the issue of parameter skip in URL.
Check my series on Lightning Web Components here to get complete hands on experience.
Happy programming 🙂
it’s not working sir ( component.get(“v.pageReference”).state.code; )
Error : [Cannot read property ‘state’ of undefined]
Make sure you have implemented lighting: isUrlAddressable interface. As per your error message I think that is missing.
Nikky, Please add this check in init method. if(component.get(“v.pageReference”) != undefined && component.get(“v.pageReference”) != ‘undefined’)
Same error, and I have lighting:isUrlAddressable, what would be the error? I used the same code that you mention and I obtain the error: Action failed: c:Upload_GDrive$controller$doInit [Cannot read property ‘state’ of null], when I tried to use the lightning component on a page
Yep…me too. And in addiion when I just removed that check and just authenticate each time, the file transfer did not work either. Failed each time.
Dave, Please try above solution and let me know if you still face any issue.
Thanks for mentioning you are using it in lightning page. Just add this check in init method if(component.get(“v.pageReference”) != undefined && component.get(“v.pageReference”) != ‘undefined’). I have added same in code as well.
if(component.get(“v.pageReference”) != undefined && component.get(“v.pageReference”) != ‘undefined’) Not working
Hi, is there any up-date to this? Tried to add the line what you mentioned in comments but still not working. I´d really appreciate that 🙂
Where are you using this? In Lightning page, VF, anywhere else?
Thank you for your reply!
I am using it in Lightning page only. 🙂
We are using “pageReference” to get attribute from URL. But it is not supported in flexipages so you need to use another way to get URL from parameter. You need to update Init method for this.
Hello, I still have error when tried to load file, it just at the 100% gives an error with Cant upload your file.
Is there any solution? When I go on Google Drive Auth button, its just redirects me to google with error No_Oauth_State: State was not sent back
Make sure you have follow all the steps. Looks like you have missing some configuration.
How to print access token on console.
Just keep that in any variable and then pass that in JS controller and then you can easily display it.
How can I print Access Token on console.
Not working. Can you Elaborate more!
You just need to return the variable in which you are getting access token to JS controller. Then you can print it.
component.get(“v.pageReference”) is undefined so the control doesn’t enters if body and nothing work, what could be the reason ?
Are you using it in lightning detail page? Because in that this method is not supported.
In the above code
lightning controller plz add this format this will work for you .
lighting:isurladdressable is not working properly so use in this format.
this is working fine to me .
doInit : function(component, event, helper) {
if(component.get(“v.pageReference”) != undefined && component.get(“v.pageReference”) != ‘undefined’) {
var code = component.get(“v.pageReference”).state.code;
var url = window.location.href;
console.log(‘url’,url);
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, ‘\\$&’);
//console.log(‘—name–‘,name);
var regex = new RegExp(‘[?&]’ + name + ‘(=([^&#]*)|&|#|$)’),
results = regex.exec(url);
console.log(‘===results==’,results);
if (!results) return null;
if (!results[2]) return ”;
return decodeURIComponent(results[2].replace(/\+/g, ‘ ‘));
}
var code = getParameterByName(‘code’);
console.log(‘–code–‘,code);
if(code != undefined) {
var action = component.get(“c.getAccessToken”);
action.setParams({
“code” : code
});
action.setCallback(this, function(response){
var status = response.getState();
if(status === “SUCCESS”){
var accessToken = response.getReturnValue();
component.set(“v.accessToken”, accessToken);
}
});
$A.enqueueAction(action);
}
}
},
Thanks for sharing Surya. I will check and update.
Code needs to be updated.
1. AuthURl is missing state , after page redirect if sate is missing then Salesforce will not allow to login back.
2. If state, is even provided then to get code from pageReference is not working as the parameters from URL is getting removed before even landing back to lighting component page. I am stuck with this and not getting the right answer from anywhere.
Here is what I posted my question in salesforce stack exchange
https://salesforce.stackexchange.com/questions/304099/upload-file-to-google-drive-from-lightning-component-page-redirect-removing-ur
https://releasenotes.docs.salesforce.com/en-us/spring19/release-notes/rn_forcecom_general_namespace_prefix_cruc_reminder.htm Due to this update Salesforce remove the parameters. I suggest you to do Auth using VF. I will check here and once found will update.
I trying to above process am getting below error while authenticating with google Salesforce will not allow to login back.
We can’t log you in because of the following error. For more information, contact your Salesforce administrator.
No_Oauth_State: State was not sent back
Please help me out.
Thank you
Hi Manu,
Due to recent Salesforce URL changes this is not working as expected. Read my previous comments. I suggest you try this with VF
Thanks for your information Tushar, and can you tell me one thing so now we can not develop this functionality any more or any possible approaches are there in lightning ..?? Or we can achieve this functionality only with vf page…??
please give me some clarification about it….
I am trying few solutions here, once found I will update.
Hi Tushar, Did you found any Solution. Im also facing that parameter dissapear on Page load
Can we upload multiple files in one rest call? I dont find any documentation for it
I don’t think we can upload multiple file in a single call.
Really Awesome stuff. I’m curious if anyone has found a workaround to get this embedded on lightning pages and flows? Also if you haven’t yet you might consider throwing this on the appexchange!
Has anyone found the solution to use it in Lightning page??
Thank you Tushar.
I am getting error like “Google hasn’t verified this app” Please help me to verify my app on google.
I tried to add domain url but worked.
You need to check your app setting in google app. There you will get option to verify your app.