1
votes

I am using a service account to connect to the Google Drive of a G Suite. I understand that with the available access (scope: https://www.googleapis.com/auth/drive.file) I can only see the files that the service account has created and using the /auth/drive scope (which gives full visibility) requires special Google approval.

I need to be able to expand the service account's visibility to include files in at least 1 folder the user has not created. I can't get this through normal folder sharing as best I can tell.

Does anyone know how to do this?

Edit to include code (written in Apex, which is similar to Java). Still pretty rough, I haven't cleaned it up yet but:

private static String buildAuthBody(Google_Drive_Integration__mdt mdt) {

    //Builds and encodes the JWT header
    String bodyHeader = '{"alg":"RS256","typ":"JWT"}';
    String encodedHeader = encode(bodyHeader);

    //Builds and encodes the JWT Claim Set. See googleAuth body
    googleAuth ga = new googleAuth(mdt);
    String claimSetString = JSON.serialize(ga);
    String encodedClaimSet = encode(claimSetString);

    //Builds out necessary pieces for Crypt.sign(algorithmName, input, privateKey). Input = body
    String signatureBody = encodedHeader + '.' + encodedClaimSet;
    signatureBody = signatureBody.replaceAll('=','');
    String encodedSignatureBody = EncodingUtil.urlEncode(signatureBody,'UTF-8');
    Blob signatureBodyBlob = Blob.valueOf(encodedSignatureBody);

    Blob key = EncodingUtil.base64Decode(mdt.Service_Account_Private_Key__c); //Must be decoded to pass into method w/o error

    //Builds the signature
    Blob signatureBlob = Crypto.sign('RSA-SHA256', signatureBodyBlob , key);
    String encodedSignature = encodeBlob(signatureBlob);

    //Sets grant type
    String grantType = EncodingUtil.urlEncode('urn:ietf:params:oauth:grant-type:jwt-bearer', 'UTF-8');

    //Sets body and debugs to rebuild body
    System.debug('grant type: grant_type=' + grantType);
    System.debug('&assertion=');
    System.debug('encoded header: '+encodedHeader);
    System.debug('encoded claim set: '+encodedClaimSet);
    System.debug('encoded signature: '+encodedSignature);



    //Build and return the body
    String body = 'grant_type=' + grantType;
    body += '&assertion=';
    body += signatureBody;
    body += '.' + encodedSignature;
    return body;
}

class googleAuth {
    public String iss; //'[email protected]';
    public String scope = 'https://www.googleapis.com/auth/drive';
    public String aud = 'https://www.googleapis.com/oauth2/v4/token';
    public Long exp;
    public Long iat;

    googleAuth(Google_Drive_Integration__mdt mdt) {
        DateTime dt = DateTime.now();
        iat = dt.getTime() / 1000;
        exp = iat + 3600; 
        iss = mdt.Service_Account_User_Email__c;
    }
}

private static String encode(String str) {
    Blob b = Blob.valueOf(str);
    String ret = EncodingUtil.base64Encode(b);
    ret = EncodingUtil.urlEncode(ret, 'UTF-8');
    return ret;
}

private static String encodeBlob(Blob b) {
    String ret = EncodingUtil.base64Encode(b);
    ret = EncodingUtil.urlEncode(ret, 'UTF-8');
    return ret;
}
1

1 Answers

1
votes

I think you are misunderstanding things about service accounts and about scopes.

enter image description here

Scopes define the amount of access a user has granted to your application. In this case the user is the service account. Using scope: https://www.googleapis.com/auth/drive.file with a service account doesn't make much sense really as you the developer own the service account and there by own its drive account. so really just give it full access using scope: https://www.googleapis.com/auth/drive there is no real reason for you to limit it. If you had a normal application using Oauth2 you would only request the access you need to the users drive account.

I need to be able to expand the service account's visibility to include files in at least 1 folder the user has not created. I can't get this through normal folder sharing as best I can tell.

I am not sure i understand this. Assuming that when you say "user" you mean the service account. I am going to assume this folder is part of your gsuite system. In which case you simply need to have your Gsuite admin set up domain wide delegation to the service account and it will have access. This is a way of granting the service account permissions to access data on your gsuite account kind of like adding a new user to the system.