/// <summary> /// Receive the code from an OAuth server /// </summary> /// <param name="authorizeMode">AuthorizeModes</param> /// <param name="codeReceiverSettings">ICodeReceiverSettings</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>IDictionary with information</returns> public Task<IDictionary<string, string>> ReceiveCodeAsync(AuthorizeModes authorizeMode, ICodeReceiverSettings codeReceiverSettings, CancellationToken cancellationToken = default(CancellationToken)) { if (codeReceiverSettings.RedirectUrl == null) { throw new ArgumentNullException(nameof(codeReceiverSettings.RedirectUrl), "The EmbeddedBrowserCodeReceiver needs a redirect url."); } // while the listener is beging starter in the "background", here we prepare opening the browser var uriBuilder = new UriBuilder(codeReceiverSettings.AuthorizationUri) { Query = codeReceiverSettings.AuthorizationUri.QueryToKeyValuePairs() .Select(x => new KeyValuePair<string, string>(x.Key, x.Value.FormatWith(codeReceiverSettings))) .ToQueryString() }; Log.Verbose().WriteLine("Opening Uri {0}", uriBuilder.Uri.AbsoluteUri); // Needs to run on th UI thread. return Dispatcher.CurrentDispatcher.Invoke(async () => await Task.Run(() => { var oAuthLoginForm = new OAuthLoginForm(codeReceiverSettings.CloudServiceName, new Size(codeReceiverSettings.EmbeddedBrowserWidth, codeReceiverSettings.EmbeddedBrowserHeight), uriBuilder.Uri, codeReceiverSettings.RedirectUrl); if (oAuthLoginForm.ShowDialog() == DialogResult.OK) { return oAuthLoginForm.CallbackParameters; } return null; }, cancellationToken)); }
/// <summary> /// The OAuth code receiver /// </summary> /// <param name="authorizeMode">AuthorizeModes tells you which mode was used to call this</param> /// <param name="codeReceiverSettings"></param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Dictionary with values</returns> public async Task<IDictionary<string, string>> ReceiveCodeAsync(AuthorizeModes authorizeMode, ICodeReceiverSettings codeReceiverSettings, CancellationToken cancellationToken = default(CancellationToken)) { Uri redirectUri; if (codeReceiverSettings.RedirectUrl == null) { redirectUri = new[] {0}.CreateLocalHostUri(); // TODO: This will create a problem that with the next "authorize" call it will try to use the same Url, while it might not work // But not setting it, will create a problem in the replacement codeReceiverSettings.RedirectUrl = redirectUri.AbsoluteUri; } else { if (!codeReceiverSettings.RedirectUrl.StartsWith("http:")) { var message = $"The LocalServerCodeReceiver only works for http URLs, not for {0}, use a different AuthorizeMode."; Log.Error().WriteLine(message); throw new ArgumentException(message, nameof(codeReceiverSettings.RedirectUrl)); } redirectUri = new Uri(codeReceiverSettings.RedirectUrl); } var listenTask = redirectUri.ListenAsync(async httpListenerContext => { // Process the request var httpListenerRequest = httpListenerContext.Request; Log.Debug().WriteLine("Got request {0}", httpListenerRequest.Url); // we got the result, parse the Query and set it as a result var result = httpListenerRequest.Url.QueryToDictionary(); try { var htmlContent = HttpContentFactory.Create(ClosePageResponse.Replace("CloudServiceName", codeReceiverSettings.CloudServiceName)); htmlContent.SetContentType(MediaTypes.Html.EnumValueOf()); await httpListenerContext.RespondAsync(htmlContent, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { Log.Error().WriteLine(ex, "Couldn't write a response"); } return result; }, cancellationToken); // while the listener is beging starter in the "background", here we prepare opening the browser var uriBuilder = new UriBuilder(codeReceiverSettings.AuthorizationUri) { Query = codeReceiverSettings.AuthorizationUri.QueryToKeyValuePairs() .Select(x => new KeyValuePair<string, string>(x.Key, x.Value.FormatWith(codeReceiverSettings))) .ToQueryString() }; // Get the formatted FormattedAuthUrl var authorizationUrl = uriBuilder.Uri; Log.Debug().WriteLine("Opening a browser with: {0}", authorizationUrl.AbsoluteUri); // Open the url in the default browser Process.Start(authorizationUrl.AbsoluteUri); // Return result of the listening return await listenTask.ConfigureAwait(false); }
/// <summary> /// The OAuth code receiver implementation /// </summary> /// <param name="authorizeMode">which of the AuthorizeModes was used to call the method</param> /// <param name="codeReceiverSettings"></param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Dictionary with values</returns> public Task<IDictionary<string, string>> ReceiveCodeAsync(AuthorizeModes authorizeMode, ICodeReceiverSettings codeReceiverSettings, CancellationToken cancellationToken = default(CancellationToken)) { var result = new Dictionary<string, string>(); var oauth1Settings = codeReceiverSettings as OAuth1Settings; if (oauth1Settings != null) { result.Add(OAuth1Parameters.Token.EnumValueOf(), oauth1Settings.RequestToken); } return Task.FromResult<IDictionary<string, string>>(result); }
/// <summary> /// The OAuth code receiver /// </summary> /// <param name="authorizeMode">which of the AuthorizeModes was used to call the method</param> /// <param name="codeReceiverSettings"></param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Dictionary with values</returns> public async Task<IDictionary<string, string>> ReceiveCodeAsync(AuthorizeModes authorizeMode, ICodeReceiverSettings codeReceiverSettings, CancellationToken cancellationToken = default(CancellationToken)) { // Force OOB Uri switch (authorizeMode) { case AuthorizeModes.OutOfBound: codeReceiverSettings.RedirectUrl = "urn:ietf:wg:oauth:2.0:oob"; break; case AuthorizeModes.OutOfBoundAuto: codeReceiverSettings.RedirectUrl = "urn:ietf:wg:oauth:2.0:oob:auto"; break; default: throw new NotSupportedException($"Only {AuthorizeModes.OutOfBound} and {AuthorizeModes.OutOfBoundAuto} are supported modes for this receiver"); } // while the listener is beging starter in the "background", here we prepare opening the browser var uriBuilder = new UriBuilder(codeReceiverSettings.AuthorizationUri) { Query = codeReceiverSettings.AuthorizationUri.QueryToKeyValuePairs() .Select(x => new KeyValuePair<string, string>(x.Key, x.Value.FormatWith(codeReceiverSettings))) .ToQueryString() }; // Get the formatted FormattedAuthUrl var authorizationUrl = uriBuilder.Uri; Log.Info().WriteLine("Opening a browser with: {0}", authorizationUrl.AbsoluteUri); // Open the url in the default browser Process.Start(authorizationUrl.AbsoluteUri); // TODO: Get the response here, this should be done via the windows title await Task.Delay(10*1000, cancellationToken).ConfigureAwait(false); // Return result of the listening return null; }
/// <summary> /// The OAuth code receiver /// </summary> /// <param name="authorizeMode">AuthorizeModes tells you which mode was used to call this</param> /// <param name="codeReceiverSettings"></param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Dictionary with values</returns> public async Task <IDictionary <string, string> > ReceiveCodeAsync(AuthorizeModes authorizeMode, ICodeReceiverSettings codeReceiverSettings, CancellationToken cancellationToken = default(CancellationToken)) { Uri redirectUri; if (codeReceiverSettings.RedirectUrl == null) { redirectUri = new[] { 0 }.CreateLocalHostUri(); // TODO: This will create a problem that with the next "authorize" call it will try to use the same Url, while it might not work // But not setting it, will create a problem in the replacement codeReceiverSettings.RedirectUrl = redirectUri.AbsoluteUri; } else { if (!codeReceiverSettings.RedirectUrl.StartsWith("http:")) { var message = $"The LocalServerCodeReceiver only works for http URLs, not for {0}, use a different AuthorizeMode."; Log.Error().WriteLine(message); throw new ArgumentException(message, nameof(codeReceiverSettings.RedirectUrl)); } redirectUri = new Uri(codeReceiverSettings.RedirectUrl); } var listenTask = redirectUri.ListenAsync(async httpListenerContext => { // Process the request var httpListenerRequest = httpListenerContext.Request; Log.Debug().WriteLine("Got request {0}", httpListenerRequest.Url); // we got the result, parse the Query and set it as a result var result = httpListenerRequest.Url.QueryToDictionary(); try { var htmlContent = HttpContentFactory.Create(ClosePageResponse.Replace("CloudServiceName", codeReceiverSettings.CloudServiceName)); htmlContent.SetContentType(MediaTypes.Html.EnumValueOf()); await httpListenerContext.RespondAsync(htmlContent, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { Log.Error().WriteLine(ex, "Couldn't write a response"); } return(result); }, cancellationToken); // while the listener is beging starter in the "background", here we prepare opening the browser var uriBuilder = new UriBuilder(codeReceiverSettings.AuthorizationUri) { Query = codeReceiverSettings.AuthorizationUri.QueryToKeyValuePairs() .Select(x => new KeyValuePair <string, string>(x.Key, x.Value.FormatWith(codeReceiverSettings))) .ToQueryString() }; // Get the formatted FormattedAuthUrl var authorizationUrl = uriBuilder.Uri; Log.Debug().WriteLine("Opening a browser with: {0}", authorizationUrl.AbsoluteUri); // Open the url in the default browser Process.Start(authorizationUrl.AbsoluteUri); // Return result of the listening return(await listenTask.ConfigureAwait(false)); }
/// <summary> /// The OAuth code receiver /// </summary> /// <param name="authorizeMode">which of the AuthorizeModes was used to call the method</param> /// <param name="codeReceiverSettings"></param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Dictionary with values</returns> public async Task <IDictionary <string, string> > ReceiveCodeAsync(AuthorizeModes authorizeMode, ICodeReceiverSettings codeReceiverSettings, CancellationToken cancellationToken = default(CancellationToken)) { // Force OOB Uri switch (authorizeMode) { case AuthorizeModes.OutOfBound: codeReceiverSettings.RedirectUrl = "urn:ietf:wg:oauth:2.0:oob"; break; case AuthorizeModes.OutOfBoundAuto: codeReceiverSettings.RedirectUrl = "urn:ietf:wg:oauth:2.0:oob:auto"; break; default: throw new NotSupportedException($"Only {AuthorizeModes.OutOfBound} and {AuthorizeModes.OutOfBoundAuto} are supported modes for this receiver"); } // while the listener is beging starter in the "background", here we prepare opening the browser var uriBuilder = new UriBuilder(codeReceiverSettings.AuthorizationUri) { Query = codeReceiverSettings.AuthorizationUri.QueryToKeyValuePairs() .Select(x => new KeyValuePair <string, string>(x.Key, x.Value.FormatWith(codeReceiverSettings))) .ToQueryString() }; // Get the formatted FormattedAuthUrl var authorizationUrl = uriBuilder.Uri; Log.Info().WriteLine("Opening a browser with: {0}", authorizationUrl.AbsoluteUri); // Open the url in the default browser Process.Start(authorizationUrl.AbsoluteUri); // TODO: Get the response here, this should be done via the windows title await Task.Delay(10 * 1000, cancellationToken).ConfigureAwait(false); // Return result of the listening return(null); }
/// <summary> /// Receive the code from an OAuth server /// </summary> /// <param name="authorizeMode">AuthorizeModes</param> /// <param name="codeReceiverSettings">ICodeReceiverSettings</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>IDictionary with information</returns> public Task <IDictionary <string, string> > ReceiveCodeAsync(AuthorizeModes authorizeMode, ICodeReceiverSettings codeReceiverSettings, CancellationToken cancellationToken = default(CancellationToken)) { if (codeReceiverSettings.RedirectUrl == null) { throw new ArgumentNullException(nameof(codeReceiverSettings.RedirectUrl), "The EmbeddedBrowserCodeReceiver needs a redirect url."); } // while the listener is beging starter in the "background", here we prepare opening the browser var uriBuilder = new UriBuilder(codeReceiverSettings.AuthorizationUri) { Query = codeReceiverSettings.AuthorizationUri.QueryToKeyValuePairs() .Select(x => new KeyValuePair <string, string>(x.Key, x.Value.FormatWith(codeReceiverSettings))) .ToQueryString() }; Log.Verbose().WriteLine("Opening Uri {0}", uriBuilder.Uri.AbsoluteUri); // Needs to run on th UI thread. return(Dispatcher.CurrentDispatcher.Invoke(async() => await Task.Run(() => { var oAuthLoginForm = new OAuthLoginForm(codeReceiverSettings.CloudServiceName, new Size(codeReceiverSettings.EmbeddedBrowserWidth, codeReceiverSettings.EmbeddedBrowserHeight), uriBuilder.Uri, codeReceiverSettings.RedirectUrl); if (oAuthLoginForm.ShowDialog() == DialogResult.OK) { return oAuthLoginForm.CallbackParameters; } return null; }, cancellationToken))); }
/// <summary> /// The OAuth code receiver implementation /// </summary> /// <param name="authorizeMode">which of the AuthorizeModes was used to call the method</param> /// <param name="codeReceiverSettings"></param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Dictionary with values</returns> public Task <IDictionary <string, string> > ReceiveCodeAsync(AuthorizeModes authorizeMode, ICodeReceiverSettings codeReceiverSettings, CancellationToken cancellationToken = default) { var result = new Dictionary <string, string>(); if (codeReceiverSettings is OAuth1Settings oauth1Settings) { result.Add(OAuth1Parameters.Token.EnumValueOf(), oauth1Settings.RequestToken); } return(Task.FromResult <IDictionary <string, string> >(result)); }
/// <summary> /// The OAuth code receiver /// </summary> /// <param name="authorizeMode">which of the AuthorizeModes was used to call the method</param> /// <param name="codeReceiverSettings"></param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Dictionary with values</returns> public async Task <IDictionary <string, string> > ReceiveCodeAsync(AuthorizeModes authorizeMode, ICodeReceiverSettings codeReceiverSettings, CancellationToken cancellationToken = default) { // Force OOB Uri, if nothing is set if (string.IsNullOrEmpty(codeReceiverSettings.RedirectUrl)) { switch (authorizeMode) { case AuthorizeModes.OutOfBound: codeReceiverSettings.RedirectUrl = "urn:ietf:wg:oauth:2.0:oob"; break; case AuthorizeModes.OutOfBoundAuto: codeReceiverSettings.RedirectUrl = "urn:ietf:wg:oauth:2.0:oob:auto"; break; default: throw new NotSupportedException($"Only {AuthorizeModes.OutOfBound} and {AuthorizeModes.OutOfBoundAuto} are supported modes for this receiver"); } } var uriBuilder = new UriBuilder(codeReceiverSettings.AuthorizationUri) { Query = codeReceiverSettings.AuthorizationUri.QueryToKeyValuePairs() .Select(x => new KeyValuePair <string, string>(x.Key, x.Value.FormatWith(codeReceiverSettings))) .ToQueryString() }; // Get the formatted FormattedAuthUrl var authorizationUrl = uriBuilder.Uri; Log.Debug().WriteLine("Opening a browser with: {0}", authorizationUrl.AbsoluteUri); // Open the url in the default browser var processStartInfo = new ProcessStartInfo(authorizationUrl.AbsoluteUri) { CreateNoWindow = true, UseShellExecute = true }; Process.Start(processStartInfo); Log.Debug().WriteLine("Waiting until a window gets a title with the state {0}", codeReceiverSettings.State); // Wait until a window get's a title which contains the state object var title = await WinEventHook.WindowTileChangeObservable() .Select(info => InteropWindowFactory.CreateFor(info.Handle).Fill()) .Where(interopWindow => !string.IsNullOrEmpty(interopWindow?.Caption)) .Where(interopWindow => interopWindow.Caption.Contains(codeReceiverSettings.State)) // Skip temporary titles, where the redirect URL os briefly seen .Where(interopWindow => interopWindow?.Caption.Contains(codeReceiverSettings.RedirectUrl) != true) .Select(interopWindow => interopWindow.Caption) .Take(1).ToTask(cancellationToken); Log.Debug().WriteLine("Got title {0}", title); if (string.IsNullOrEmpty(title)) { return(new Dictionary <string, string>()); } var match = QueryPartOfTitleRegEx.Match(title); if (!match.Success) { return(UriParseExtensions.QueryStringToDictionary(title)); } var queryParameters = match.Groups["query"]?.Value; if (string.IsNullOrEmpty(queryParameters)) { return(new Dictionary <string, string>()); } Log.Debug().WriteLine("Query parameters: {0}", queryParameters); // Return result of the listening return(UriParseExtensions.QueryStringToDictionary(queryParameters)); }