Reputation: 3955
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?
Upvotes: 1
Views: 2014
Reputation: 24153
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.
Upvotes: 1