Episode 17: User Sign Up and Simple Access Control

Jordan Griffin

Request Metrics won’t be very successful if users can’t sign up! We recently completed cookie based user authentication and distributed session using Redis but neglected initial sign up. Now we finally go back and do some boring forms and CRUD work.

A rich set of internal admin tools helps with customer support, system monitoring and visibility. We’ll start our suite of tools with a user admin page to list all users in the system. This page is access controlled using a simple filter attribute. While we’re here, we might as well let users sign out too.

The actual sign up logic is just a boring form submit and user data written to Redis. Because user CRUD was covered previously, we’ll skip it and jump to other interesting bits we ran into.

Simple Access Control with ActionFilterAttributes

Our new admin page should only be accessed by internal users. We could use the claims-based authorization built into ASP.NET Core for this, but it is a bit heavy for our taste. Instead, we use a simple ActionFilterAttribute attached to any controller or controller method that is access controlled:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Controllers
{
    [AdminOnly] // <--- Our custom attribute!
    public class AdminController : Controller
    {
        [HttpGet]
        [Route("/important-admin-stuff")]
        public async Task<IActionResult> GetImportantAdminScreen()
        {
            return Content("You have access to the admin page!")
        }
    }
}
AdminController.cs

The custom attribute just concerns itself with determining whether the currently authenticated user is an administrator:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace MyApp
{
    public class AdminOnlyAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            base.OnActionExecuting(context);

            if (!IsUserAnAdmin(context))
            {
                context.Result = new UnauthorizedResult();
            }
        }

        private bool IsUserAnAdmin(ActionExecutingContext context)
        {
            // Your application specific code here!
            // For example's sake, all authenticated users are considered admins.
            return context.HttpContext.User.Identity.IsAuthenticated;
        }
    }
}
AdminOnlyAttribute.cs

Sign Out a User and Clear Session

We have forgotten about sign out in the midst of all this signing in and signing up. A user should be de-authorized and their session cleared when they sign out. We settle for clearing all data contained within the user’s session because ASP.NET Core no longer has a way to abandon or destroy a session:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Controllers
{
    public class LoginController : Controller
    {
        [HttpPost]
        [Route("/signout")]
        public async Task<IActionResult> SignOut()
        {
            // Signout of cookie based auth
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

            // Clear all data from the user's session.
            // NOTE: This does not destroy the session itself!
            HttpContext.Session.Clear();

            return this.Redirect("/login");
        }

        // ...snip (other login methods here)...
    }
}
LoginController.cs

User sign up and authentication is done for now. Next, we’ll change gears and start working on the Request Metrics JavaScript browser agent!

Sam the Sloth throwing a paper airplane

Get Tips on Web Performance

Join Sam the Performance Sloth's newsletter for fresh web performance reviews, ideas, and tools.

Subscribe
Chart page views and the distribution user load time

About Request Metrics

The easiest way to monitor your web performance. Request Metrics records how real users experience your website and shows you simplified metrics and alerting. And at a price that's easy on your budget.