diff --git a/SecurityService.UserInterface/Pages/Account/Login/Index.cshtml.cs b/SecurityService.UserInterface/Pages/Account/Login/Index.cshtml.cs index b240a8d..3e972b0 100644 --- a/SecurityService.UserInterface/Pages/Account/Login/Index.cshtml.cs +++ b/SecurityService.UserInterface/Pages/Account/Login/Index.cshtml.cs @@ -146,70 +146,118 @@ private async Task HandleLoginButton(AuthorizationRequest? contex private async Task BuildModelAsync(string returnUrl) { - Input = new InputModel + Input = CreateInputModel(returnUrl); + + var context = await _interaction.GetAuthorizationContextAsync(returnUrl); + + if (await TryBuildSingleIdpViewAsync(context)) + return; + + var providers = await GetExternalProvidersAsync(context?.Client); + + View = CreateViewModel(context?.Client, providers); + } + + private InputModel CreateInputModel(string returnUrl) => + new() { ReturnUrl = returnUrl }; - - var context = await _interaction.GetAuthorizationContextAsync(returnUrl); - if (context?.IdP != null && await _schemeProvider.GetSchemeAsync(context.IdP) != null) - { - var local = context.IdP == Duende.IdentityServer.IdentityServerConstants.LocalIdentityProvider; - // this is meant to short circuit the UI and only trigger the one external IdP - View = new ViewModel - { - EnableLocalLogin = local, - }; + private async Task TryBuildSingleIdpViewAsync(AuthorizationRequest? context) + { + if (context?.IdP == null) + return false; - Input.Username = context?.LoginHint; + if (await _schemeProvider.GetSchemeAsync(context.IdP) == null) + return false; - if (!local) - { - View.ExternalProviders = new[] { new ViewModel.ExternalProvider { AuthenticationScheme = context.IdP } }; - } + var isLocal = context.IdP == Duende.IdentityServer.IdentityServerConstants.LocalIdentityProvider; - return; - } + View = new ViewModel + { + EnableLocalLogin = isLocal, + ExternalProviders = isLocal + ? Array.Empty() + : new[] + { + new ViewModel.ExternalProvider + { + AuthenticationScheme = context.IdP + } + } + }; + + Input.Username = context.LoginHint; + return true; + } + private async Task> GetExternalProvidersAsync(Client? client) + { + var providers = await GetStaticProvidersAsync(); + providers.AddRange(await GetDynamicProvidersAsync()); + + return ApplyClientRestrictions(providers, client); + } + + private async Task> GetStaticProvidersAsync() + { var schemes = await _schemeProvider.GetAllSchemesAsync(); - var providers = schemes - .Where(x => x.DisplayName != null) - .Select(x => new ViewModel.ExternalProvider + return schemes + .Where(s => s.DisplayName != null) + .Select(s => new ViewModel.ExternalProvider { - DisplayName = x.DisplayName ?? x.Name, - AuthenticationScheme = x.Name - }).ToList(); + AuthenticationScheme = s.Name, + DisplayName = s.DisplayName! + }) + .ToList(); + } + + private async Task> GetDynamicProvidersAsync() + { + var schemes = await _identityProviderStore.GetAllSchemeNamesAsync(); - var dyanmicSchemes = (await _identityProviderStore.GetAllSchemeNamesAsync()) - .Where(x => x.Enabled) - .Select(x => new ViewModel.ExternalProvider + return schemes + .Where(s => s.Enabled) + .Select(s => new ViewModel.ExternalProvider { - AuthenticationScheme = x.Scheme, - DisplayName = x.DisplayName + AuthenticationScheme = s.Scheme, + DisplayName = s.DisplayName }); - providers.AddRange(dyanmicSchemes); + } + private List ApplyClientRestrictions( + List providers, + Client? client) + { + if (client == null) + return providers; - var allowLocal = true; - var client = context?.Client; - if (client != null) - { - allowLocal = client.EnableLocalLogin; - if (client.IdentityProviderRestrictions != null && client.IdentityProviderRestrictions.Any()) - { - providers = providers.Where(provider => client.IdentityProviderRestrictions.Contains(provider.AuthenticationScheme)).ToList(); - } + Input.ClientId = client.ClientId; - Input.ClientId = client.ClientId; + if (client.IdentityProviderRestrictions?.Any() == true) + { + providers = providers + .Where(p => client.IdentityProviderRestrictions.Contains(p.AuthenticationScheme)) + .ToList(); } - View = new ViewModel + return providers; + } + + private ViewModel CreateViewModel( + Client? client, + IEnumerable providers) + { + var allowLocal = client?.EnableLocalLogin ?? true; + + return new ViewModel { AllowRememberLogin = LoginOptions.AllowRememberLogin, EnableLocalLogin = allowLocal && LoginOptions.AllowLocalLogin, - ExternalProviders = providers.ToArray(), + ExternalProviders = providers.ToArray() }; } + } \ No newline at end of file