Eitan
Eitan

Reputation: 1386

BigQuery using authentication without browser prompt

I am using bigquery with authentication.

I have built an authentication key, such as 'https://console.developers.google.com/apis/credentials?project=...' - OAuth 2.0 client IDs,

I am using visual studio 2015, and installed from nuget: googles.apis.bigQuery.v2.

Also, I wrote in package manager console: Install-Package Google.Cloud.BigQuery.V2 -Pre

I am trying to connect to bigquery - I succeed doing that, but when I create credentials, I am prompted for gmail account login + accept some scope privileges for access.

I don't want to be prompt.


Also - in my code, when login with credentials - even my credentials are incorrect, I succeed connect to the project.

Here is my code:

                projectId = "myproject";

            string[] scopes = new string[] { BigqueryService.Scope.Bigquery,                // view and manage your BigQuery data
                                 BigqueryService.Scope.BigqueryInsertdata ,     // Insert Data into Big query
                                 BigqueryService.Scope.CloudPlatform,           // view and manage your data acroos cloud platform services
                                 BigqueryService.Scope.DevstorageFullControl,   // manage your data on Cloud platform services
                                 BigqueryService.Scope.DevstorageReadOnly ,     // view your data on cloud platform servies
                                 BigqueryService.Scope.DevstorageReadWrite };
            using (var stream = new FileStream("clientsecret.json", FileMode.Open, FileAccess.Read))
            {
                ClientSecrets cs = GoogleClientSecrets.Load(stream).Secrets;

                GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
                {

                    ClientSecrets = cs,
                    Scopes = scopes,
                    DataStore = new FileDataStore("Store")
                });
                UserCredential credentail;
                credentail = GoogleWebAuthorizationBroker.AuthorizeAsync(
                    cs,
                    scopes
                    , "username"
                    , CancellationToken.None
                    , new FileDataStore("Store")).Result; 
                    // ***** Here the Chrome explorer is opened, and I asked to login to gmail etc...
                    // Nevertheless, I
                    // ... rest of code.
            }

Here is the json file: clientsecret.json

{
 "installed": {
"client_id": "xxx",
"project_id": "xxx",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "xxx",
"redirect_uris": [ "urn:ietf:wg:oauth:2.0:oob", "http://localhost" ]
}
}

I have tried using flow and add credential as following:

            GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
            {

                ClientSecrets = cs,
                Scopes = scopes,
                DataStore = new FileDataStore("Store")
            });

                TokenResponse tokenResponse = null;
                //                    tokenResponse = new TokenResponse { RefreshToken = "120" , ExpiresInSeconds = 0};
                tokenResponse = new TokenResponse { RefreshToken = "120",  ExpiresInSeconds = -1};
  ...
  credentail = new UserCredential(flow, "Spotoption-BG-other", tokenResponse);

The above is instead of the credential setting as previous. When I trying retrieving data like:

string query = "select ...";
JobsResource j = Service.Jobs;
QueryRequest qr = new QueryRequest();
QueryResponse response = j.Query(qr, projectId).Execute();

I got exception at last line: Additional information: Error:"invalid_grant", Description:"", Uri:""

When I do:

bool b = flow.ShouldForceTokenRetrieval();

I got: false.

When tokenResponse = null, I got the message (after QueryResponse response =):

Additional information: Object reference not set to an instance of an object.

Upvotes: 0

Views: 918

Answers (1)

Eitan
Eitan

Reputation: 1386

To use Google authentication without browser prompt, you have to use a token.

The token is return when first accepting the scopes, and after that you can keep that token and send it back to google-api for second use.

Refresh token is permanent for the user.

Here is a code for retrieving the token first time (browser is opening for accepting the terms for scopes):

        public TokenResponse GetToken()
    {
        UserCredential credentail;

        try
        {
            string[] scopes = new string[] { BigqueryService.Scope.Bigquery,    // view and manage your BigQuery data
                                BigqueryService.Scope.BigqueryInsertdata ,  // Insert Data into Big query
                                BigqueryService.Scope.CloudPlatform,        // view and manage your data acroos cloud platform services
                                BigqueryService.Scope.DevstorageFullControl,// manage your data on Cloud platform services
                                BigqueryService.Scope.DevstorageReadOnly ,  // view your data on cloud platform servies
                                BigqueryService.Scope.DevstorageReadWrite };


            credentail = GoogleWebAuthorizationBroker.AuthorizeAsync(
                _clientSecret,
                scopes,
                "reports"
                , CancellationToken.None
                , new FileDataStore("Store")
                ).Result;
            if (credentail != null)
                return credentail.Token;
            else
            {
                _log.WriteToAll("Invalid credentials", EventLogEntryType.Error);
                return null;
            }
        }
        catch (Exception ex)
        {
            _log.WriteToAll(ex);
            return null;
        }
    }

After retrieving the token, it can be sent by the flow as I gave in my example:

                TokenResponse tokenResponse = null;
            tokenResponse = new TokenResponse
            {
                RefreshToken = refreshToken
            };

Upvotes: 1

Related Questions