Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 57 additions & 56 deletions SecurityService.UserInterface/Pages/Account/Login/Index.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace IdentityServerHost.Pages.Login;

using Polly;
using System;
using System.Linq;
using System.Threading.Tasks;
Expand Down Expand Up @@ -63,86 +64,86 @@ public async Task<IActionResult> OnGet(string returnUrl)
public async Task<IActionResult> OnPost()
{
// check if we are in the context of an authorization request
var context = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl);
AuthorizationRequest? context = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl);

// the user clicked the "cancel" button
if (Input.Button == "forgotpassword") {
return Redirect($"ForgotPassword/Index?clientId={Input.ClientId}");
}

// the user clicked the "cancel" button
if (Input.Button != "login")
if (Input.Button != "login") {
return await HandleCancelButton(context);
}

if (ModelState.IsValid) {
return await HandleLoginButton(context);
}

// something went wrong, show form with error
await BuildModelAsync(Input.ReturnUrl);
return Page();
}

private async Task<IActionResult> HandleCancelButton(AuthorizationRequest? context) {
if (context != null)
{
if (context != null)
// if the user cancels, send a result back into IdentityServer as if they
// denied the consent (even if this client does not require consent).
// this will send back an access denied OIDC error response to the client.
await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);

// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
if (context.IsNativeClient())
{
// if the user cancels, send a result back into IdentityServer as if they
// denied the consent (even if this client does not require consent).
// this will send back an access denied OIDC error response to the client.
await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);
// The client is native, so this change in how to
// return the response is for better UX for the end user.
return this.LoadingPage(Input.ReturnUrl);
}

// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
if (context.IsNativeClient())
{
return Redirect(Input.ReturnUrl);
}

// since we don't have a valid context, then we just go back to the home page
return Redirect("~/");
}

private async Task<IActionResult> HandleLoginButton(AuthorizationRequest? context) {
var result = await _signInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberLogin, lockoutOnFailure: true);
if (result.Succeeded) {
var user = await _userManager.FindByNameAsync(Input.Username);
await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName, clientId: context?.Client.ClientId));

if (context != null) {
if (context.IsNativeClient()) {
// The client is native, so this change in how to
// return the response is for better UX for the end user.
return this.LoadingPage(Input.ReturnUrl);
}

// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
return Redirect(Input.ReturnUrl);
}
else
{
// since we don't have a valid context, then we just go back to the home page
return Redirect("~/");
}
}

if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberLogin, lockoutOnFailure: true);
if (result.Succeeded)
{
var user = await _userManager.FindByNameAsync(Input.Username);
await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName, clientId: context?.Client.ClientId));

if (context != null)
{
if (context.IsNativeClient())
{
// The client is native, so this change in how to
// return the response is for better UX for the end user.
return this.LoadingPage(Input.ReturnUrl);
}

// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
return Redirect(Input.ReturnUrl);
}
// request for a local page
if (Url.IsLocalUrl(Input.ReturnUrl)) {
return Redirect(Input.ReturnUrl);
}

// request for a local page
if (Url.IsLocalUrl(Input.ReturnUrl))
{
return Redirect(Input.ReturnUrl);
}
else if (string.IsNullOrEmpty(Input.ReturnUrl))
{
return Redirect("~/");
}
else
{
// user might have clicked on a malicious link - should be logged
throw new ArgumentException("invalid return URL");
}
if (string.IsNullOrEmpty(Input.ReturnUrl)) {
return Redirect("~/");
}

await _events.RaiseAsync(new UserLoginFailureEvent(Input.Username, "invalid credentials", clientId:context?.Client.ClientId));
ModelState.AddModelError(string.Empty, LoginOptions.InvalidCredentialsErrorMessage);
// user might have clicked on a malicious link - should be logged
throw new ArgumentException("invalid return URL");
}

// something went wrong, show form with error
await BuildModelAsync(Input.ReturnUrl);
return Page();
await _events.RaiseAsync(new UserLoginFailureEvent(Input.Username, "invalid credentials", clientId: context?.Client.ClientId));
ModelState.AddModelError(string.Empty, LoginOptions.InvalidCredentialsErrorMessage);

return this.Page();
}

private async Task BuildModelAsync(string returnUrl)
{
Input = new InputModel
Expand Down
Loading