2

Currently I have codes which the user authorize before they can access the files inside their own Google Drives account using OAuth2 however now I want to hardcode the authentication part and authorization part into the source code for the aspx.cs page.

Is it possible? The language I currently am using right now is in ASPx together with C#. I used this using ASPSnippets.GoogleAPI; for the codes below.

Here are the codes for my 0Auth2 using client secret and client id

protected void Page_Load(object sender, EventArgs e)
{
    GoogleConnect.ClientId = "client_id";
    GoogleConnect.ClientSecret = "client_secret";
    GoogleConnect.RedirectUri = Request.Url.AbsoluteUri.Split('?')[0];
    GoogleConnect.API = EnumAPI.Drive;
    if (!string.IsNullOrEmpty(Request.QueryString["code"]))
    {
        string code = Request.QueryString["code"];
        string json = GoogleConnect.Fetch("me", code);
        GoogleDriveFiles files = new JavaScriptSerializer().Deserialize<GoogleDriveFiles>(json);

        //Remove the deleted files.
        dlFiles.DataSource = files.Items.Where(i => i.Labels.Trashed == false);
        dlFiles.DataBind();
    }
    else if (Request.QueryString["error"] == "access_denied")
    {
        ClientScript.RegisterClientScriptBlock(this.GetType(), "alert", "alert('Access denied.')", true);
    }
    else
    {
        GoogleConnect.Authorize("https://www.googleapis.com/auth/drive.readonly");
    }
}
Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
Marko233
  • 65
  • 1
  • 9
  • *Is it possible?* No, the whole point of OAuth is that you never see the user credentials, the authorisation is off loaded to google, that way users can be sure that you don't get access to their google credentials. So you can't cache(hard code) credentials that you never see. If I remember google providers auth methods that use tokens that you need to configure on their site, this is the mechanism you need to use – Liam Jan 12 '18 at 09:10
  • I'd suggest you read the docs https://developers.google.com/identity/protocols/OAuth2, your after "service accounts", but this also explains why the mechanism your trying to get working won't work, i.e. [this diagram](https://developers.google.com/accounts/images/tokenflow.png) from that page – Liam Jan 12 '18 at 09:13
  • Then you can't do it. You either need to use a service account or offload the auth to the user (in which case you can't access the username/password), they're your only options. If you could cache the users token, etc. it would be a security hole, OAuth is explicitly deigned to prevent this – Liam Jan 12 '18 at 09:34
  • and what if I don't want to use service account cause it not what I initially want to do if I decided to use service account, then what is left is using the token you mention? – Marko233 Jan 12 '18 at 09:35
  • ah i see ok ty for the info – Marko233 Jan 12 '18 at 09:36
  • the important thing to notice is where the user enters their username and password in ["User login and Consent" in this diagram](https://developers.google.com/accounts/images/tokenflow.png), it's the "Google Servers" not your servers – Liam Jan 12 '18 at 09:38

2 Answers2

1

I am not sure which code it is you would like to hard code.

  1. Access token (only good for an hour not worth hard coding)
  2. Refresh token (long lived can be hard coded but not a good idea see below)
  3. Client id (yes you can hard code this.)
  4. Client secret (yes you can hard code this)

The way this works is that you request access from a user and you get a refresh token back you should store these refresh tokens. If the user wants to login again or if you need to access their data again you use the refresh token to request a new access token and they you have access to the users data.

Assuming that you have a list of these refresh tokens you could hard code them in your application for use later. However this is a bad idea. Refresh tokens can expire.

  1. The user can remove your access
  2. Refresh tokens not used for six months will be automatically expired
  3. If the user has requested more then 50 refresh tokens the older ones will stop working
  4. Random Google bugs

Due to this it is a good idea for your application to have the ability to request access from the user again if needed.

This is code for authenticating using the google .net client library it stores the user credentials. If the user doesn't have a valid refresh token then it will prompt the user for access again.

private static UserCredential GetUserCredential(string clientSecretJson, string userName, string[] scopes)
    {
        try
        {
            if (string.IsNullOrEmpty(userName))
                throw new ArgumentNullException("userName");
            if (string.IsNullOrEmpty(clientSecretJson))
                throw new ArgumentNullException("clientSecretJson");
            if (!File.Exists(clientSecretJson))
                throw new Exception("clientSecretJson file does not exist.");

            // These are the scopes of permissions you need. It is best to request only what you need and not all of them               
            using (var stream = new FileStream(clientSecretJson, FileMode.Open, FileAccess.Read))
            {
                string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
                credPath = Path.Combine(credPath, ".credentials/", System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);

                // Requesting Authentication or loading previously stored authentication for userName
                var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
                                                                         scopes,
                                                                         userName,
                                                                         CancellationToken.None,
                                                                         new FileDataStore(credPath, true)).Result;

                credential.GetAccessTokenForRequestAsync();
                return credential;
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Get user credentials failed.", ex);
        }
    }

With these credentials stored you will not need to prompt a user for access again.

Note: A service account should IMO only be used if you as a developer would like to share information on a google drive account that you control. Service accounts should not be used to access private user data. Thats what Oauth2 is for.

Note 2: You may hard code your client id and secret although you may consider putting it in a config file. Or just using the client secrete json like the above example does.

Code ripped from my sample project

Service account VS Oauth2

If the files are on a users Google Drive account then you need access. You are going to have to ask them for access there is no way around that and it has nothing to do with the client library this is how Oauth works. If you are trying to access private data owned by a user you need their permission.

If you are trying to access a Google Drive account that you personally control and want to grant said users access to a file on that account then you should be using a service account. You can grant a service account permission to access your google drive account by taking the service account email address and sharing a directory with it. The service account will then have access to that directory. Another one of my tutorials here Google Drive with service accounts

You might find my tutorial series useful Google Development for beginners this part is on service accounts Google Developer service accounts

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • OP was asking if he could "hard code" details. I'm guessing they don't want to prompt the user at all – Liam Jan 12 '18 at 10:30
  • I have updated my answer to include information about hard codeing the refresh token, but i have added info on why it is a bad idea to hard code the refresh token. Note 2 includes info about storing the client id and secret as it is unclear what token it is he wants to hard code. – Linda Lawton - DaImTo Jan 12 '18 at 10:40
  • @DalmToIf I were to hardcode refresh token, when the token is almost expired, it wont prompt the user to the authorize page and ask the user to authorize again right? – Marko233 Jan 13 '18 at 10:23
  • My code will only prompt the user if the refresh token becomes invalid. It Will automatically get a new access token without promoting the user – Linda Lawton - DaImTo Jan 13 '18 at 11:27
  • @DalmTo When I tried to put your code into my aspx.cs, I got some error at the `!file.Exists`, The error says it `is an ambiguous reference between 'System.IO.File' and 'Google.Apis.Drive.v3.Data.File'` – Marko233 Jan 15 '18 at 01:20
  • 1
    Declare it as System.IO.File – Linda Lawton - DaImTo Jan 15 '18 at 07:14
  • @DalmTo ok so back to the authorization part, what if I don't want the user to authorize the permission, or rather I don't want the authorize page to be display, it just jump straight in to the drive because I just want to allow them to access the files inside and does not required the user to perform any action to access it, all they had to do is just click a button and they are in the drive but the button is not meant for the user to allow or disallow the access to the drive, in this case I use service account? – Marko233 Jan 16 '18 at 06:03
  • I have updated my anwser with information on service accounts vs oauth2 – Linda Lawton - DaImTo Jan 16 '18 at 07:21
  • @DalmTo is there anyway I could contact you if I have faced any problems regarding the service account? Besides the stackoverflow. – Marko233 Jan 16 '18 at 08:06
  • Daimto.com is my website there is a contact form – Linda Lawton - DaImTo Jan 16 '18 at 08:19
  • @DalmTo What did you declare for the string[] scope in your service account sample in github for v3, cause im getting an error for it – Marko233 Jan 16 '18 at 08:22
  • probably something like new [] { DriveService.Scope.Drive }; but it depends on what access you need – Linda Lawton - DaImTo Jan 16 '18 at 08:34
0

Tl;Dr No there is no way to "hardcode the authentication part"

It seems like your trying to bypass your users entering their usernames and passwords on the Google Servers. You can't do this. OAuth is explicitly designed to prevent users having to share their Google credentials with your site:

enter image description here

Using OAuth 2.0 to Access Google APIs

notice in the above that the User enters their "User login & Consent" into the Google Servers, not your server. All you see is the token response. This will give you a window of access into that users information, but will then expire, requiring you to get a new Token. So you never see any information that could be usefully hardcoded.

The system is explicitly designed to prevent you from hardcode(ing [sic]) the authentication part.

Your only option is to use a Service Account if you want to not prompt the user for consent. Now that said, it looks to me as though this isn't supported (understandably) for Google Drive.

This question covers accessing your own drive and how you can achieve this. But you con't do this to access other peoples drives.

Liam
  • 27,717
  • 28
  • 128
  • 190
  • Service accounts are supported by Google drive and most of Googles apis with the exception of (YouTube, Blogger, and webmastertools (not 100% sure about the last one)) – Linda Lawton - DaImTo Jan 12 '18 at 10:26
  • OP wants to access **other users** drives though, a service account isn't going to allow this. Google Cloud would work but not end users drives – Liam Jan 12 '18 at 10:28
  • Actually it does you just have to take the service account email address and share any folder on google drive with it and it will have access. Assuming you want to ask your users to do this you can use a service account to access their data. https://developers.google.com/identity/protocols/OAuth2ServiceAccount – Linda Lawton - DaImTo Jan 12 '18 at 10:34
  • But what I want is to access the Drive in my own account not the service account, and be able to do whatever I want in there like download files and view files, etc. when I run the webpage. So after reading what you guys wrote there only service account and refresh token which could do what I want correct? or rather only refresh token? – Marko233 Jan 13 '18 at 10:29