1

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,

1 Answer 1

1

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:

  1. Adding parameter into HttpContext.Items
  2. Adding claim to current User.Identity

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);
            }
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for shining the way. I think I choose HttpContext.Items because of using JWT in my application :)

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.