예제 #1
0
        // 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);
        }