// https://developers.google.com/identity/protocols/OAuth2InstalledApp public static OAuthRequest BuildLoopbackRequest(params string[] scopes) { var request = new OAuthRequest { CodeVerifier = RandomDataBase64Url(32), Scopes = scopes }; string codeChallenge = Base64UrlEncodeNoPadding(Sha256(request.CodeVerifier)); const string codeChallengeMethod = "S256"; string scope = BuildScopes(scopes); request.RedirectUri = string.Format("http://{0}:{1}/", IPAddress.Loopback, GetRandomUnusedPort()); request.State = RandomDataBase64Url(32); request.AuthorizationRequestUri = string.Format("{0}?response_type=code&scope=openid%20profile{6}&redirect_uri={1}&client_id={2}&state={3}&code_challenge={4}&code_challenge_method={5}", AuthorizationEndpoint, Uri.EscapeDataString(request.RedirectUri), ClientId, request.State, codeChallenge, codeChallengeMethod, scope); return(request); }
private async void HandleRedirect() { this.State.Token = null; // for example, let's pretend I want also want to have access to WebAlbums var scopes = new[] { "https://picasaweb.google.com/data/" }; var request = OAuthRequest.BuildLoopbackRequest(scopes); var listener = new HttpListener(); listener.Prefixes.Add(request.RedirectUri); listener.Start(); // note: add a reference to System.Windows.Presentation and a 'using System.Windows.Threading' for this to compile await this.Dispatcher.BeginInvoke(new Action(() => { this.Wb.Navigate(request.AuthorizationRequestUri); })); // here, we'll wait for redirection from our hosted webbrowser var context = await listener.GetContextAsync(); // browser has navigated to our small http servern answer anything here string html = "<html><body></body></html>"; var buffer = Encoding.UTF8.GetBytes(html); context.Response.ContentLength64 = buffer.Length; var stream = context.Response.OutputStream; var responseTask = stream.WriteAsync(buffer, 0, buffer.Length).ContinueWith(task => { stream.Close(); listener.Stop(); }); string error = context.Request.QueryString["error"]; if (error != null) { return; } string state = context.Request.QueryString["state"]; if (state != request.State) { return; } string code = context.Request.QueryString["code"]; this.State.Token = request.ExchangeCodeForAccessToken(code); }