Versatile OpenID Connect stack for ASP.NET Core and Microsoft.Owin (compatible with ASP.NET 4.6.1)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

157 lines
6.1 KiB

using System.Windows;
using Dapplo.Microsoft.Extensions.Hosting.Wpf;
using OpenIddict.Abstractions;
using OpenIddict.Client;
using static OpenIddict.Abstractions.OpenIddictConstants;
using static OpenIddict.Abstractions.OpenIddictExceptions;
using static OpenIddict.Client.WebIntegration.OpenIddictClientWebIntegrationConstants;
namespace OpenIddict.Sandbox.Wpf.Client;
public partial class MainWindow : Window, IWpfShell
{
private readonly OpenIddictClientService _service;
public MainWindow(OpenIddictClientService service)
{
_service = service ?? throw new ArgumentNullException(nameof(service));
InitializeComponent();
}
private async void LocalLoginButton_Click(object sender, RoutedEventArgs e)
=> await LogInAsync("Local");
private async void LocalLoginWithGitHubButton_Click(object sender, RoutedEventArgs e)
=> await LogInAsync("Local", new()
{
[Parameters.IdentityProvider] = Providers.GitHub
});
private async void LocalLogoutButton_Click(object sender, RoutedEventArgs e)
=> await LogOutAsync("Local");
private async void GitHubLoginButton_Click(object sender, RoutedEventArgs e)
=> await LogInAsync(Providers.GitHub);
private async Task LogInAsync(string provider, Dictionary<string, OpenIddictParameter>? parameters = null)
{
// Disable the buttons to prevent concurrent operations.
LocalLogin.IsEnabled = false;
LocalLoginWithGitHub.IsEnabled = false;
LocalLogout.IsEnabled = false;
GitHubLogin.IsEnabled = false;
try
{
using var source = new CancellationTokenSource(delay: TimeSpan.FromSeconds(90));
try
{
// Ask OpenIddict to initiate the authentication flow (typically, by starting the system browser).
var result = await _service.ChallengeInteractivelyAsync(new()
{
AdditionalAuthorizationRequestParameters = parameters,
CancellationToken = source.Token,
ProviderName = provider
});
// Wait for the user to complete the authorization process and authenticate the callback request,
// which allows resolving all the claims contained in the merged principal created by OpenIddict.
var principal = (await _service.AuthenticateInteractivelyAsync(new()
{
CancellationToken = source.Token,
Nonce = result.Nonce
})).Principal;
MessageBox.Show($"Welcome, {principal.FindFirst(Claims.Name)!.Value}.",
"Authentication successful", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (OperationCanceledException)
{
MessageBox.Show("The authentication process was aborted.",
"Authentication timed out", MessageBoxButton.OK, MessageBoxImage.Warning);
}
catch (ProtocolException exception) when (exception.Error is Errors.AccessDenied)
{
MessageBox.Show("The authorization was denied by the end user.",
"Authorization denied", MessageBoxButton.OK, MessageBoxImage.Warning);
}
catch
{
MessageBox.Show("An error occurred while trying to authenticate the user.",
"Authentication failed", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
finally
{
// Re-enable the buttons to allow starting a new operation.
LocalLogin.IsEnabled = true;
LocalLoginWithGitHub.IsEnabled = true;
LocalLogout.IsEnabled = true;
GitHubLogin.IsEnabled = true;
}
}
private async Task LogOutAsync(string provider, Dictionary<string, OpenIddictParameter>? parameters = null)
{
// Disable the buttons to prevent concurrent operations.
LocalLogin.IsEnabled = false;
LocalLoginWithGitHub.IsEnabled = false;
LocalLogout.IsEnabled = false;
GitHubLogin.IsEnabled = false;
try
{
using var source = new CancellationTokenSource(delay: TimeSpan.FromSeconds(90));
try
{
// Ask OpenIddict to initiate the logout flow (typically, by starting the system browser).
var result = await _service.SignOutInteractivelyAsync(new()
{
AdditionalEndSessionRequestParameters = parameters,
CancellationToken = source.Token,
ProviderName = provider
});
// Wait for the user to complete the logout process and authenticate the callback request.
//
// Note: in this case, only the claims contained in the state token can be resolved since
// the authorization server doesn't return any other user identity during a logout dance.
await _service.AuthenticateInteractivelyAsync(new()
{
CancellationToken = source.Token,
Nonce = result.Nonce
});
MessageBox.Show($"The user was successfully logged out from the local server.",
"Logout demand successful", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (OperationCanceledException)
{
MessageBox.Show("The logout process was aborted.",
"Logout timed out", MessageBoxButton.OK, MessageBoxImage.Warning);
}
catch
{
MessageBox.Show("An error occurred while trying to log the user out.",
"Logout failed", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
finally
{
// Re-enable the buttons to allow starting a new operation.
LocalLogin.IsEnabled = true;
LocalLoginWithGitHub.IsEnabled = true;
LocalLogout.IsEnabled = true;
GitHubLogin.IsEnabled = true;
}
}
}