Sign in and manage editors

SunBird's sign-in is the site's sign-in. AddSunBird() sets up ASP.NET Identity, stores the accounts in SunBird's own tables, and adds the sign-in and account pages. There is no seeded account and no default password. SunBird emails editors their invites and password reset links, so the site needs a way to send email.

What the site needs

SunBird's pages are Razor Pages inside the HCI.SunBird package, and it sends email through HCI.Email. In Program.cs:

builder.Services.AddRazorPages();
builder.Services.AddSendGridEmail(builder.Configuration);   // HCI.Email.SendGrid, or any HCI.Email IEmailService
builder.AddSunBird().UseSqlServer(builder.Configuration.GetConnectionString("SunBird")!);
// ...
app.MapSunBird();
app.UseStaticFiles();   // or app.MapStaticAssets(); serves SunBird's stylesheet
app.MapRazorPages();    // maps SunBird's pages as well as the site's own

and in configuration:

{
  "SunBird": {
    "SiteUrl": "https://www.example.co.uk",
    "Email": {
      "From": "noreply@example.co.uk"
    }
  }
}

SiteUrl is the site's public address. The links in SunBird's emails are built from it, never from the address a request came in on, so a forged request cannot send an editor a real email that links to someone else's site. Each page's canonical address is built from it too (see SEO page settings). On App Service, set it as a deployment slot setting (SunBird__SiteUrl), so emails sent from staging link to staging.

MapSunBird() stops the site starting, with a clear message, if no HCI.Email IEmailService is registered or From or SiteUrl is missing.

ASP.NET Core adds the authentication and authorization middleware by itself. If the site calls app.UseRouting() itself, also call app.UseAuthentication() and app.UseAuthorization() after it.

On a developer's machine

To follow invite and reset links locally without a mail provider, register an IEmailService that writes each email to the log, as the sample site does:

builder.Services.AddSingleton<IEmailService, LogEmailService>();

The sign-in cookie is Secure, so sign in over https (https://localhost:...), not plain http.

The pages

Page Who What it does
/sunbird/setup Anyone, once Creates the first admin, given the setup code. Closed for good once any account exists.
/sunbird/login Anyone Signs in with email and password. Sends people to setup while no account exists.
/sunbird/logout Signed in Signs out. Signing out takes a POST, so a link elsewhere cannot sign an editor out.
/sunbird/forgot-password Anyone Emails a link to choose a new password.
/sunbird/reset-password From the email Chooses a new password.
/sunbird/invite From the email An invited user chooses their password and is signed in.
/sunbird/confirm-email From the email Confirms a change of email.
/sunbird/account Signed in Change your own password, display name and email.
/sunbird/users Admins Invite and edit users; resend an invite; set a one-time password; make and revoke access tokens for agents; suspend and reactivate.

The pages carry noindex, and use their own small stylesheet, not the site's layout.

Roles

Role Can
Editor Edit content, and manage their own account.
Admin Everything an editor can, and manage users.

The first account is an admin. An admin cannot suspend themselves or remove their own admin role, and the last active admin cannot be suspended or made an editor, so a site always has someone who can manage users.

1. Create the first admin

Set a setup code in the site's configuration. Keep it out of source control: use an App Service setting, or user secrets on a developer's machine.

Where Setting
App Service SunBird__SetupCode = a long random value
Developer's machine dotnet user-secrets set "SunBird:SetupCode" "<a long random value>"

Then open /sunbird/setup, enter the code, your email, display name and password, and choose Create admin. You are signed in and taken to the users page.

Wrong setup codes count like failed sign-ins: after SunBird:Lockout:MaxFailedAttempts wrong codes, setup refuses every code for SunBird:Lockout:Minutes. Once the first account exists, setup is closed even if the code is still set. You can then remove the setting.

Staging and the live site share one database, so the first admin only needs creating once, on either.

2. Invite editors

On /sunbird/users, choose Invite a user, and enter their email, display name and role. SunBird emails them a link to choose their own password. The link works once, for 3 days, and using it confirms their email. Until then the user shows as Invited and cannot sign in.

If the invite email cannot be sent, the user is still saved, and SunBird says so. Fix the email settings, then open the user and choose Resend invite. A link that has run out is replaced the same way.

3. Forgotten passwords

Forgotten your password? on the sign-in page leads to /sunbird/forgot-password. SunBird emails a link to choose a new password. The link works once, for 2 hours, and using it signs out the account's other sessions.

The page always says the same thing, whether or not an account uses that email, so it cannot be used to find out who has an account. Nothing is sent to a suspended account or one that has not accepted its invite.

4. Change your email

On /sunbird/account, enter the new email and your current password. SunBird emails a link to the new address; your email, which is also what you sign in with, changes only when you use it. The link works once, for 24 hours.

5. When email is not working

An admin can open a user and set a one-time password, and give it to them in person. It replaces their password (and works for a user who has not accepted their invite yet). When they sign in, SunBird asks them to choose their own password before they can do anything else.

6. Suspend or reactivate an account

Open the account from /sunbird/users and choose Suspend. A suspended account cannot sign in, its open sessions end within a minute, and its agent access tokens stop working at once. Accounts are never deleted, because the page history records who saved and published each version. Reactivate lets the account sign in again.

Branding the emails

SunBird's emails can carry the client's name, logo, colour and footer through the SunBird:Email settings BrandName, LogoUrl, AccentColour and FooterText. See Settings.

Note

Coming: replacing SunBird's email templates with a site's own.

Passwords and lockout

By default a password needs at least 12 characters, and five failed sign-ins in a row lock an account for 15 minutes. Change either per site in configuration; see Settings.

Staying signed in across restarts and slot swaps

The sign-in cookie is protected by the site's ASP.NET Core Data Protection keys. If the keys are not kept somewhere every instance and deployment slot shares, editors are signed out when the site restarts or the slots swap. Configure Data Protection key storage in the site's Program.cs.