GoogleWebAuthorizationBroker.AuthorizeAsync Hangs GoogleWebAuthorizationBroker.AuthorizeAsync Hangs asp.net asp.net

GoogleWebAuthorizationBroker.AuthorizeAsync Hangs


Found a way to get passed this.

I used GoogleAuthorizationCodeFlow instead. this is what it turned out to look like:

        ClientSecrets secrets = new ClientSecrets()        {            ClientId = CLIENT_ID,            ClientSecret = CLIENT_SECRET        };        var token = new TokenResponse { RefreshToken = REFRESH_TOKEN };         var credentials = new UserCredential(new GoogleAuthorizationCodeFlow(            new GoogleAuthorizationCodeFlow.Initializer             {                ClientSecrets = secrets            }),             "user",             token);        var service = new YouTubeService(new BaseClientService.Initializer()        {            HttpClientInitializer = credentials,            ApplicationName = "TestProject"        });


It is possible to break out if this, for example using a timeout, because the AuthorizeAsync method has the implementation of a CancellationToken.

  • Create a TokenSource to obtain the Token itself.
  • Set the Cancellation of the TokenSource to i.e. 20 Seconds
  • Extract the token to pass to the AuthorizeAsync method.

public async void RunAsync(){    UserCredential credential;    var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read);    CancellationTokenSource cts = new CancellationTokenSource();    cts.CancelAfter(TimeSpan.FromSeconds(20));    CancellationToken ct = cts.Token;    credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(    GoogleClientSecrets.Load(stream).Secrets,    new[] { YouTubeService.Scope.YoutubeUpload },    "user",    ct    );    if (ct.IsCancellationRequested) return;    // do more stuff when came back authorized.}

Now, after 20 seconds, when the AuthorizeAsync was not completed, the caller of this method RunAsync will receive an Exception.

try{    await RunAsync();}catch(Exception){     // "Timeout" of the RunAsync(); }


The following code lets you use your google drive api credentials to request login information from the user, and download the file to your server to perform some request:

Option Strict OnOption Explicit OnImports System.NetImports System.IOImports System.LinqImports System.ThreadingImports System.WebImports System.Web.UI.WebControlsImports GoogleImports Google.Apis.Auth.OAuth2Imports Google.Apis.Auth.OAuth2.FlowsImports Google.Apis.Auth.OAuth2.WebImports Google.Apis.Services'for driveImports Google.Apis.Drive.v2Imports Google.Apis.Drive.v2.DataImports Google.Apis.Util.Store'for AuthorizationCodeRequestUrlImports Google.Apis.Auth.OAuth2.RequestsImports System.DrawingPublic Class _Default    Inherits Page    Private redirect_uri As String = ""    Private client_id As String = ""    Private client_secret As String = ""    Private service As DriveService    'Application logic should manage users authentication.     'This sample works with only one user. You can change it by retrieving    'data from the session.    'You use the word user because you are authorized by the user to access    'their drive contents.Private UserId As String = "user" Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load    Dim SCOPES As String() = New [String]() {"https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/drive.install"}    Dim flow As GoogleAuthorizationCodeFlow    'use extended class to create google authorization code flow    'use custom own datastore    flow = New ForceOfflineGoogleAuthorizationCodeFlow(New GoogleAuthorizationCodeFlow.Initializer() With {    .DataStore = New FileDataStore("D:\inetpub\wwwroot\go\filedatastore", True),    .ClientSecrets = New ClientSecrets() With {        .ClientId = client_id,        .ClientSecret = client_secret    },    .Scopes = SCOPES})    Dim uri = Request.Url.ToString()    Dim redirecturi As String = redirect_uri    Dim code = Request("code")    If code IsNot Nothing Then        output.Text &= "<br />Code: " & code & "<br />"        output.Text &= "<br />UserID: " & UserId & "<br />"        output.Text &= "<br />URI: " & uri & "<br />"        output.Text &= "<br />RedirectURI: " & redirecturi & "<br />"        output.Text &= "<br />uri-substring-thing: " & uri.Substring(0, uri.IndexOf("?")) & "<br />"        Dim token = flow.ExchangeCodeForTokenAsync(UserId, code, redirecturi, CancellationToken.None).Result        ' Extract the right state.        Dim oauthState = AuthWebUtility.ExtracRedirectFromState(flow.DataStore, UserId, Request("state")).Result        Response.Redirect(oauthState)    Else        Dim result = New AuthorizationCodeWebApp(flow, redirecturi, uri).AuthorizeAsync(UserId, CancellationToken.None).Result        If result.RedirectUri IsNot Nothing Then            ' Redirect the user to the authorization server.            Response.Redirect(result.RedirectUri)        Else            ' The data store contains the user credential, so the user has been already authenticated.            service = New DriveService(New BaseClientService.Initializer() With {            .HttpClientInitializer = result.Credential,            .ApplicationName = "Drive API Sample"        })        End If    End IfEnd Sub''' <summary>''' Download a file''' Documentation: https://developers.google.com/drive/v2/reference/files/get''' </summary>''' <param name="_service">a Valid authenticated DriveService</param>''' <param name="_fileResource">File resource of the file to download</param>''' <param name="_saveTo">location of where to save the file including the file name to save it as.</param>''' <returns></returns>Public Shared Function downloadFile(_service As DriveService, _fileResource As Data.File, _saveTo As String) As [Boolean]    If Not [String].IsNullOrEmpty(_fileResource.DownloadUrl) Then        Try            Dim x = _service.HttpClient.GetByteArrayAsync(_fileResource.DownloadUrl)            Dim arrBytes As Byte() = x.Result            System.IO.File.WriteAllBytes(_saveTo, arrBytes)            Return True        Catch e As Exception            Console.WriteLine("An error occurred: " + e.Message)            Return False        End Try    Else        ' The file doesn't have any content stored on Drive.        Return False    End IfEnd FunctionPublic Async Function GetFile(IncomingFileID As String) As Tasks.Task    Try        Dim request As FilesResource.GetRequest = service.Files.Get(IncomingFileID)        Dim response As Data.File = Await request.ExecuteAsync(CancellationToken.None)        downloadFile(service, response, "D:/inetpub/wwwroot/go/" & Guid.NewGuid.ToString)    Catch ex As Exception        Dim str As String = "<br />" & ex.ToString()        str = str.Replace(Environment.NewLine, Environment.NewLine + "<br/>")        str = str.Replace("  ", "  ")        output.Text &= String.Format("<font color=""red"">{0}</font>", str)    End TryEnd Function'''<summary>Gets the File Lists of the user.</summary>Public Async Function FetchFilelists() As System.Threading.Tasks.Task    Try        ' Get all files of the user asynchronously.        Dim request As FilesResource.ListRequest = service.Files.List()        'get only my files        request.Q = "mimeType contains 'image/'"        Dim response As FileList = Await request.ExecuteAsync()        ShowFilelists(response)    Catch ex As Exception        Dim str = ex.ToString()        str = str.Replace(Environment.NewLine, Environment.NewLine + "<br/>")        str = str.Replace("  ", "  ")        output.Text = String.Format("<font color=""red"">{0}</font>", str)    End TryEnd FunctionPrivate Sub ShowFilelists(response As FileList)    If response.Items Is Nothing Then        output.Text &= "You have no files!<br/>"        Return    End If    output.Text &= "Showing files...<br/>"    Dim ctr As Integer = 0    For Each file As Google.Apis.Drive.v2.Data.File In response.Items        ctr += 1        Dim listPanel As New Panel() With {            .BorderWidth = Unit.Pixel(1),            .BorderColor = Color.Black        }        listPanel.Controls.Add(New Label() With {            .Text = file.Title + "--" + file.MimeType                })        listPanel.Controls.Add(New Label() With {            .Text = "<hr/>"            })        If file.MimeType.ToString().Contains("folder") = False Then            listPanel.Controls.Add(New HyperLink() With {            .Text = "Download",            .NavigateUrl = file.WebContentLink        })            listPanel.Controls.Add(New Button() With {                                   .Text = "Use This Image", .OnClientClick = "document.getElementById('currentImageId').value = '" & file.Id & "';return false;"})        End If        lists.Controls.Add(listPanel)    Next    output.Text &= "Total Files: " & ctr.ToStringEnd SubProtected Async Sub listButton_Click(sender As Object, e As EventArgs) Handles listbutton.Click    Await FetchFilelists()End SubProtected Async Sub DownloadImageButton_Click(sender As Object, e As EventArgs) Handles DownloadImageButton.Click    Dim idToUse As String = Page.Request.Form(currentImageId.UniqueID)    output.Text &= "<br />Attempting to download id: " & idToUse & "<br />"    Await GetFile(idToUse)    output.Text &= "<br />Download Completed<br />"End Sub'overwrite. force offline.Friend Class ForceOfflineGoogleAuthorizationCodeFlow    Inherits GoogleAuthorizationCodeFlow    'source: //gotoanswer.stanford.edu/google_analytics_oauth_with_accesstype__offline_in_c-4478263/    Public Sub New(initializer As GoogleAuthorizationCodeFlow.Initializer)        MyBase.New(initializer)    End Sub    Public Overrides Function CreateAuthorizationCodeRequest(redirectUri As String) As AuthorizationCodeRequestUrl        Dim ss = New Google.Apis.Auth.OAuth2.Requests.GoogleAuthorizationCodeRequestUrl(New Uri(AuthorizationServerUrl))        ss.AccessType = "offline"        ss.ApprovalPrompt = "force"        ss.ClientId = ClientSecrets.ClientId        ss.Scope = String.Join(" ", Scopes)        ss.RedirectUri = redirectUri        Return ss    End FunctionEnd ClassEnd Class

Here's the WebForm .aspx page:

<%@ Page Title="Home Page" Language="VB" MasterPageFile="~/Site.Master"AutoEventWireup="true" CodeBehind="Default.aspx.vb"     Inherits="PictureMyCard._Default" Async="True" %><asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server"><div>    <asp:Button ID="listbutton" runat="server" ClientIDMode="Static" Text="list" /><asp:Label id="output" runat="server" ClientIDMode="Static" Text="..." ></asp:Label></div>    <asp:Label ID="lists" ClientIDMode="Static" Text="..." runat="server"></asp:Label><hr /><asp:HiddenField ClientIDMode="Static" ID="currentImageId" runat="server" /><asp:Button runat="server" ID="DownloadImageButton" ClientIDMode="Static"  Text="Download Image to server" /></asp:Content>