Reputation: 3151
I'm converting my asp.net framework to asp.net core.
One thing I'm facing with is saving query data in Authentication context in authorizationhandler.
In my asp.net framework, I've done with my AuthorizeAttribute in ASP.Net Framework:
public override void OnAuthorization(HttpActionContext actionContext)
{
// Retrieve email and password.
var accountEmail =
actionContext.Request.Headers.Where(
x =>
!string.IsNullOrEmpty(x.Key) &&
x.Key.Equals(HeaderFields.RequestAccountEmail))
.Select(x => x.Value.FirstOrDefault())
.FirstOrDefault();
// Retrieve account password.
var accountPassword =
actionContext.Request.Headers.Where(
x =>
!string.IsNullOrEmpty(x.Key) &&
x.Key.Equals(HeaderFields.RequestAccountPassword))
.Select(x => x.Value.FirstOrDefault()).FirstOrDefault();
// Invalid account name or password.
if (string.IsNullOrEmpty(accountEmail) || string.IsNullOrEmpty(accountPassword))
{
// Treat this request is unauthorized.
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, new
{
Error = $"{Language.WarnAccountNotLogin}"
});
return;
}
// Find the hashed password from the original one.
var accountHashedPassword = RepositoryAccountExtended.FindMd5Password(accountPassword);
// Retrieve person whose properties match conditions.
var person = RepositoryAccountExtended.FindPerson(null, accountEmail, accountHashedPassword, null, null);
// No person has been found.
if (person == null)
{
// Treat this request is unauthorized.
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, new
{
Error = $"{Language.WarnAccountNotLogin}"
});
return;
}
// Account has been disabled.
if ((StatusAccount) person.Status == StatusAccount.Inactive)
{
// Treat the login isn't successful because of disabled account.
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, new
{
Error = $"{Language.WarnDisabledAccount}"
});
return;
}
// Account is still pending.
if ((StatusAccount) person.Status == StatusAccount.Pending)
{
// Treat the login isn't successful because of pending account.
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, new
{
Error = $"{Language.WarnPendingAccount}"
});
return;
}
// Account role isn't enough to access the function.
if (!Roles.Any(x => x == person.Role))
{
// Role isn't valid. Tell the client the access is forbidden.
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden, new
{
Error = $"{Language.WarnForbiddenAccessMethod}"
});
}
// Store the requester information in action argument.
actionContext.ActionArguments[HeaderFields.Account] = person;
}
As you see, I stored my query data (Account - in this situation) in the actionContext, and I can access to it later in Controllers.
My question is: How can I achieve the same thing in ASP.NET Core, because I don't want to query my database in my every AuthorizationHandler.
Thank you,
Upvotes: 1
Views: 671
Reputation: 24123
How can I achieve the same thing in ASP.NET Core
First you need an authentication middleware, for your case it may be basic authentication. For Aspnet Core there is no built-in basic authentication middleware. A soluton is here or you can implement own authentication middleware like this.
I stored my query data (Account - in this situation) in the actionContext, and I can access to it later in Controllers.
Two possible ways are coming to my mind:
HttpContext.Items
To implement this you can use ClaimsTransformation or custom middleware after authentication middleware. If you go with your own implementation you can also use HandleAuthenticateAsync
method.
Update
It seems right place to save query data is HandleAuthenticateAsync
. If you use @blowdart's basic authentication solution, your code might be something like below:
.....
await Options.Events.ValidateCredentials(validateCredentialsContext);
if (validateCredentialsContext.Ticket != null)
{
HttpContext.Items[HeaderFields.Account] = person; // assuming you retrive person before this
Logger.LogInformation($"Credentials validated for {username}");
return AuthenticateResult.Success(validateCredentialsContext.Ticket);
}
Upvotes: 1