1

I need to authenticate my users using an external API from the login page. If the authentication from the external API succeed then I store at the session a AuthToken.

To check if the request is valid I have created the following Authorization Handler

public class ExtApiStoreRequirement : IAuthorizationRequirement
{
}
public class ExtApiAuthorizationHandler : AuthorizationHandler<ExtApiStoreRequirement>
{

    IHttpContextAccessor _accessor;
    public ExtApiAuthorizationHandler(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ExtApiStoreRequirement requirement)
    {
        var authState = GET_AUTH_FROM_SESSION(_accessor.HttpContext.Session);


        if (authState!=null)
        {
            _accessor.HttpContext.Response.Redirect("/Account/Login");
            //context.Fail(); <-- I removed that because it was responding an empty page
            context.Succeed(requirement);
        }
        else
            context.Succeed(requirement);

        return Task.CompletedTask;
    }
}

And I have registered this handler at my startup.cs

  services.AddAuthorization(options =>
        {
            options.AddPolicy("ExtApi",
                              policy => policy.Requirements.Add(new ExtApiStoreRequirement()));
        });

This approach is working but I don't feel confident because I have to call context.Succeed(requirement); for the redirection to work. If I call context.Fail() then no redirection takes place and all I see is an empty page.

Is there any security issue with this approach or I will be safe using it?

1 Answer 1

1

Your implementation is for authorization not authentication. I think instead of creating an authorization policy, writing custom authentication middleware would be right way for your case.

First see how to implement custom authentication Simple token based authentication/authorization in asp.net core for Mongodb datastore

To implement above way for your case HandleAuthenticateAsync should be something like below:

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
    AuthenticateResult result = null;
    var principal = GetPrincipalFromSession();
    if(principal != null)
    {
         result = AuthenticateResult.Success(new AuthenticationTicket(principal,
                    new AuthenticationProperties(), Options.AuthenticationScheme));
    }
    else
    {
         result = AuthenticateResult.Skip();
    }
    return result;
}

Update based on comment:

protected override async Task<bool> HandleUnauthorizedAsync(ChallengeContext context)
{    
     Response.Redirect(Options.LoginPath);// you need to define LoginPath        
     return true;
}

Also you should store principal in session when user signs in.

Sign up to request clarification or add additional context in comments.

2 Comments

Where is the redirection to login page if not authorized?
You are right, i missed this. You can override HandleUnauthorizedAsync to redirection. See my update.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.