Identity User Admin Feature

INFO

When using ServiceStack Auth refer to Admin Users UI instead

Registration

The Identity Auth Admin UI can be enabled when registering the AuthFeature Plugin by calling AdminUsersFeature():

public class ConfigureAuth : IHostingStartup
{
    public void Configure(IWebHostBuilder builder) => builder
        .ConfigureServices(services => {
            services.AddPlugin(new AuthFeature(IdentityAuth.For<ApplicationUser>(
                options => {
                    // options.SessionFactory = () => new CustomUserSession(); //optional
                    options.CredentialsAuth();
                    options.AdminUsersFeature();
                })));
        });
}

Which just like the ServiceStack Auth Admin Users UI enables a Admin UI that's only accessible to Admin Users for managing Identity Auth users at /admin-ui/users.

User Search Results

Which displays a limited view of a User's info due to the minimal properties on the default IdentityAuth model:

Custom Search Result Properties

These User Search results are customizable by specifying the ApplicationUser properties you want displayed instead:

options.AdminUsersFeature(feature =>
{
    feature.QueryIdentityUserProperties =
    [
        nameof(ApplicationUser.Id),
        nameof(ApplicationUser.DisplayName),
        nameof(ApplicationUser.Email),
        nameof(ApplicationUser.UserName),
        nameof(ApplicationUser.LockoutEnd),
    ];
});

Custom Search Result Behavior

The default display Order of Users is also customizable:

feature.DefaultOrderBy = nameof(ApplicationUser.DisplayName);

As well as the Search behavior which can be replaced to search any custom fields, e.g:

feature.SearchUsersFilter = (q, query) =>
{
    var queryUpper = query.ToUpper();
    return q.Where(x =>
        x.DisplayName!.Contains(query) ||
        x.Id.Contains(queryUpper) ||
        x.NormalizedUserName!.Contains(queryUpper) ||
        x.NormalizedEmail!.Contains(queryUpper));
};

Default Create and Edit Users Forms

The default Create and Edit Admin Users UI are also limited to editing the minimal IdentityAuth properties:

Whilst the Edit page includes standard features to lockout users, change user passwords and manage their roles:

Custom Create and Edit Forms

By default Users are locked out indefinitely, but this can also be changed to lock users out to a specific date, e.g:

feature.ResolveLockoutDate = user => DateTimeOffset.Now.AddDays(7);

The forms editable fields can also be customized to include additional properties, e.g:

feature.FormLayout =
[
    Input.For<ApplicationUser>(x => x.UserName, c => c.FieldsPerRow(2)),
    Input.For<ApplicationUser>(x => x.Email, c => { 
        c.Type = Input.Types.Email;
        c.FieldsPerRow(2); 
    }),
    Input.For<ApplicationUser>(x => x.FirstName, c => c.FieldsPerRow(2)),
    Input.For<ApplicationUser>(x => x.LastName, c => c.FieldsPerRow(2)),
    Input.For<ApplicationUser>(x => x.DisplayName, c => c.FieldsPerRow(2)),
    Input.For<ApplicationUser>(x => x.PhoneNumber, c =>
    {
        c.Type = Input.Types.Tel;
        c.FieldsPerRow(2); 
    }),
];

That can override the new ApplicationUser Model that's created and any Validation:

Custom User Creation

feature.CreateUser = () => new ApplicationUser { EmailConfirmed = true };
feature.CreateUserValidation = async (req, createUser) =>
{
    await IdentityAdminUsers.ValidateCreateUserAsync(req, createUser);
    var displayName = createUser.GetUserProperty(nameof(ApplicationUser.DisplayName));
    if (string.IsNullOrEmpty(displayName))
        throw new ArgumentNullException(nameof(AdminUserBase.DisplayName));
    return null;
};

Admin User Events

Should you need to, Admin User Events can use used to execute custom logic before and after creating, updating and deleting users, e.g:

feature.OnBeforeCreateUser = (request, user) => { ... };
feature.OnAfterCreateUser  = (request, user) => { ... };
feature.OnBeforeUpdateUser = (request, user) => { ... };
feature.OnAfterUpdateUser  = (request, user) => { ... };
feature.OnBeforeDeleteUser = (request, userId) => { ... };
feature.OnAfterDeleteUser  = (request, userId) => { ... };

IdentityAuth User Claims

The User Claim Management UI can be used to assign Claims to individual Users:

Validating Claims

Claims are attestations or attributes about a User which we can use to restrict access to APIs to only Users who have been assigned that claim. We could use this to implement a permission system that restricts usage with a todos:write permission with something like:

[ValidateHasClaim("perm", "todos:write")]
class CreateTodo {}

Normally this would result in the generic missing claims error message:

But as the perm claim has a customized error message:

HasClaimValidator.ClaimErrorMessages["perm"]= "`${Value} Permission Required`";

It will generate that Error Response instead:

This is a good example for how to use HasClaimValidator.ClaimErrorMessages to add custom error messages for your own custom claim validations.

Inspecting Claims inside Services

You can also inspect and validate a Users Claim by inspecting the Authenticated ClaimsPrincipal, e.g:

public class TodoServices : Service
{
    public object Any(CreateTodo request)
    {
        var user = Request.GetClaimsPrincipal();
        if (!user.HasClaim("perm", "todos:write"))
            throw HttpError.Forbidden("todos:write Permission Required");
        
        var allUserClaims = user.Claims.ToList();
        //...
    }
}