Home > database >  Getting infinite loop when adding Authentication
Getting infinite loop when adding Authentication

Time:01-05

I have Authentication API (jwt) for authentication users. Using this for several clients and am in the process of adding the second client now.. firs one works as it should. I have determent that the problem is with this section:

var _authorizePolicy = new AuthorizationPolicyBuilder()
                  .RequireAuthenticatedUser()
                  .Build();

var _serviceProvider = builder.Services.BuildServiceProvider();

var _authenticationSettings = _serviceProvider.GetService<IAuthenticationSettings>();

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                      .AddCookie(JwtBearerDefaults.AuthenticationScheme,
                        options => {
                            options.LoginPath = _authenticationSettings.LoginPath;
                            options.AccessDeniedPath = _authenticationSettings.AccessDeniedPath;
                            options.Events = new CookieAuthenticationEvents
                            {
                                // Check if JWT needs refreshment 
                                OnValidatePrincipal = RefreshTokenMonitor.ValidateAsync
                            };
                            options.Cookie.Name = "MainAppCookie";
                        }
                      );

builder.Services.AddMvc(config => 
    { 
        config.Filters.Add(new AuthorizeFilter(_authorizePolicy)); 
    })
   .AddNewtonsoftJson(options => 
    {
       options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
    })
   .AddViewOptions(options => options.HtmlHelperOptions.ClientValidationEnabled = true);

I have the same code (different name for the Cookie) is the first application and it works fine there.

Starts with this

Few seconds later....this will come up

Here you have the AccountController:

public class AccountController : Controller

{ private readonly ISecurityManager _securityManager;

public AccountController(ISecurityManager securityManager)
{
    _securityManager = securityManager;
}

public async Task<IActionResult> Login()
{
    return View(new LoginViewModel());
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login([FromForm] LoginViewModel model, string returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;

    if (!ModelState.IsValid)
    {
        ViewBag.ErrorMessage = "Input data incorrect. Please try again";
        ModelState.AddModelError(string.Empty, "Invalid login form");
        return View(model);
    }

    if (await _securityManager.LoginUser(model.Email, model.Password))
        return RedirectToLocal(returnUrl);
    else
    {
        ViewBag.ErrorMessage = "Invalid login attempt.";
        return View(model);
    }
    return View(model);
}

public async Task<IActionResult> AccessDenied()
{
    return View();
}

[HttpGet]
[Route("account/password/forgot")]
public async Task<IActionResult> ForgotPassword()
{
    return View(new ForgotPasswordModel());
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPasswordSubmit(ForgotPasswordModel model)
{
    return RedirectToAction(nameof(ForgotPasswordConfirmation));
}

[Route("account/password/confirmation")]
public async Task<IActionResult> ForgotPasswordConfirmation()
{
    return View();
}

[HttpGet]
[Route("account/password/reset")]
public async Task<IActionResult> ResetPassword()

{
    return View(new PasswordResetModel());
}

[HttpPost]
public async Task<IActionResult> ResetPasswordSubmit(PasswordResetModel model)
{
    return RedirectToAction(nameof(Login), new { });
}

public async Task<IActionResult> LogOut()
{
    //await _securityManager.LogOut();
    return RedirectToAction(nameof(Login));
}

// Prevent session stealing
private IActionResult RedirectToLocal(string returnUrl)
{
    if (Url.IsLocalUrl(returnUrl))
        return Redirect(returnUrl);
    else
        return RedirectToAction(nameof(HomeController.Index), "Home");
}

}

Here you have the actual login:

 private async Task<bool> Login(AuthResult token)
{
    if(token.Token.IsNullOrEmpty())
        return false;

    await LogOut();

    var _tokenHandler = new JwtSecurityTokenHandler();
    var _tokenSettings = _jwtTokenValidationSettings.CreateTokenValidationParameters();
    var _principal = _tokenHandler.ValidateToken(token.Token, _tokenSettings, out var _validatedToken);
    var _identity = _principal.Identity as ClaimsIdentity;
    var _securityToken = _tokenHandler.ReadToken(token.Token) as JwtSecurityToken;
    var _extraClaims = _securityToken.Claims.Where(c => !_identity.Claims.Any(x => x.Type == c.Type)).ToList();

    _extraClaims.Add(new Claim("jwt", token.Token));
    _extraClaims.Add(new Claim("refreshToken", token.RefreshToken));
    _identity.AddClaims(_extraClaims);

    var _authenticationProperties = new AuthenticationProperties()
    {
        IssuedUtc = _identity.Claims.First(c => c.Type == JwtRegisteredClaimNames.Iat)?.Value.ToInt64().ToUnixEpochDate(),
        ExpiresUtc = _identity.Claims.First(c => c.Type == JwtRegisteredClaimNames.Exp)?.Value.ToInt64().ToUnixEpochDate(),
        IsPersistent = true
    };

    await _httpContext.SignInAsync(JwtBearerDefaults.AuthenticationScheme, _principal, _authenticationProperties);
    

    return _identity.IsAuthenticated;
}

And to clarify further... This is a error I get: enter image description here

CodePudding user response:

Your LoginControler (or several of its actions) needs to have [AllowAnonymous] to allow it to bypass the auth checks. Otherwise, the user won't have permission to view those routes.

CodePudding user response:

The error was actually in [AllowAnonymous] attribute in AccountController. Removed it and build the project, added the attribute again. Works like a charm :)

  •  Tags:  
  • Related