Search code examples
asp.netoauthgoogle-oauthowin

Incremental Google OAuth with Asp.Net Owin Oauth


I'm looking for a solution to doing incremental authorization against Google's api's with Asp.Net's Owin OAuth Libraries.

I know how to set scope for specific api's, but I would like to do it incrementally and can only see how to set it on globally.

Doc on Google Oauth Incremental Auth... https://developers.google.com/accounts/docs/OAuth2WebServer#incrementalAuth

Current VB Code...

Public Sub ConfigureAuth(app As IAppBuilder)

    Dim googleCreds = New GoogleOAuth2AuthenticationOptions() With {
                .ClientId = "xxxx",
                .ClientSecret = "xxx"
    }

    googleCreds.Scope.Add("https://www.googleapis.com/auth/analytics.readonly")
    app.UseGoogleAuthentication(googleCreds)

    ' Would like to add another way to specify GoogleDrive, YouTube, Google+ scopes
    ' Example code that doesn't work that would add a 2nd Google Oauth Listener
    googleCreds.Scope.Clear()
    googleCreds.Scope.Add("https://www.googleapis.com/auth/drive.file")
    googleCreds.AuthenticationType = "GoogleDrive"
    app.UseGoogleAuthentication(googleCreds)

End Class

Solution

  • Here is the solution I came up with. It involves passing a "scope" parameter in the url and then parsing that in the "OnApplyRedirect" function of the Authentication options and then manually injecting the correct scope url into the redirect url.

        Dim googleCreds = New GoogleOAuth2AuthenticationOptions() With {
            .ClientId = "xxx",
            .ClientSecret = "xxx",
            .Provider = New Microsoft.Owin.Security.Google.GoogleOAuth2AuthenticationProvider() With { _
                .OnApplyRedirect = Function(context)
                                       Dim queryString = HttpContext.Current.Request.QueryString.ToString()
                                       Dim queryParms = HttpUtility.ParseQueryString(queryString)
    
                                       ' Change the value of "redirect" here
                                       ' e.g. append access_type=offline
                                       Dim redirect As String = context.RedirectUri
                                       redirect += "&access_type=offline"
                                       redirect += "&approval_prompt=force"
                                       redirect += "&include_granted_scopes=true"
    
                                       Dim uri = New Uri(redirect)
    
                                       If (Not String.IsNullOrEmpty(queryParms.Get("scope"))) Then
                                           Dim scope = queryParms.Get("scope")
                                           Dim redirectQueryString = HttpUtility.ParseQueryString(uri.Query)
                                           Select Case scope
                                               Case "Analytics"
                                                   redirectQueryString.Set("scope", "https://www.googleapis.com/auth/analytics.readonly")
                                               Case "YoutTube"
                                                   redirectQueryString.Set("scope", "https://gdata.youtube.com")
                                               Case "Drive"
                                                   redirectQueryString.Set("scope", "https://www.googleapis.com/auth/drive.file")
                                               Case Else
                                                   LoggingUtility.LogErrorMessage("Invalid scope passed in: scope: " + scope)
                                           End Select
                                           redirect = uri.GetLeftPart(UriPartial.Path) + "?" + redirectQueryString.ToString()
                                       End If
    
                                       context.Response.Redirect(redirect)
    
                                   End Function, _
            }
        }
    
        'Google Analytics
        app.UseGoogleAuthentication(googleCreds)