Developer Dude
Developer Dude

Reputation: 67

How to change SignOutAsync ReturnUrl in ASP .NET Core

I am using .NET Core 2-3 with EF Identity cookie auth, and I need to be able to log any given user out of all browsing "sessions" they are logged in for.

To do this, I am "invalidating" the cookie with the following authorization filter:

public class CookieIsValidRequirementHandler : AuthorizationHandler<CookieIsValidRequirement>
{
    private readonly ILogger _logger;
    private readonly SignInManager<IdentityUser> _signInManager;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public CookieIsValidRequirementHandler(
        ILogger<CookieIsValidRequirementHandler> logger,
        SignInManager<IdentityUser> signInManager,
        IHttpContextAccessor httpContextAccessor
    ) {
        _logger = logger;
        _signInManager = signInManager;
        _httpContextAccessor = httpContextAccessor;
    }
    protected override async Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        CookieIsValidRequirement requirement)
    {
        _logger.LogDebug("Checking if cookie is valid...");

        Claim userIdClaim = context.User.FindFirst(ClaimTypes.NameIdentifier);
        if (userIdClaim == null || string.IsNullOrWhiteSpace(userIdClaim.Value))
        {
            _logger.LogDebug($"NameIdentifier Claim not found");
            context.Succeed(requirement); // This is needed to allow the home page to load
            return;
        }
        else
        {
            if (requirement.userIdsToLogOut.Contains(userIdClaim.Value))
            {
                _logger.LogInformation("Cookie is invalid! Logging user out!");
                await _signInManager.SignOutAsync();
                requirement.userIdsToLogOut.Remove(userIdClaim.Value);
                _logger.LogInformation($"CAN I USE THIS??? {_httpContextAccessor.HttpContext}");
            }
            else
            {
                _logger.LogDebug("Cookie is valid!");
                context.Succeed(requirement);
            }
        }
    }

This is actually working pretty great, except that it redirects the user to:

https://localhost:5001/Identity/Account/Login?ReturnUrl=%2FIdentity%2FAccount%2FAccessDenied%3FReturnUrl%3D%252F

I like that it redirects them to the login page, but notice that the ReturnUrl is to an Access Denied page. I don't want that.

I've tried looking into the black box here: https://github.com/dotnet/aspnetcore

And it looks like the auth model is tightly related to "schemes" that are "configured" using the small handful of options available in the startup class.

Upvotes: 0

Views: 706

Answers (2)

Tore Nestenius
Tore Nestenius

Reputation: 19921

You can redirect to any page you want if you pass in a RedirectUri to SignOutAsync:

public async Task Signout()
{
    var props = new AuthenticationProperties()
    {
        RedirectUri = "/home/login"
    };

    await HttpContext.SignOutAsync("cookie", props);
}

Upvotes: 0

Abrar Ahmad
Abrar Ahmad

Reputation: 100

I don't know If I am understanding you correctly, you can config the login and access denied path in the startup file in the ConfigureServices method.

Example:

 services.AddAuthentication()
            // cookies 
            .AddCookie(options =>{
                options.LoginPath = "/Account/login";
                options.AccessDeniedPath = "/Account/login";
            }); 

 

Upvotes: 1

Related Questions