CORE MODULE

Add an Authentication Layer

What you'll learn in this guide
‍
How to structure the HTML for an authenticated landing page in CX Platform, including the bits that make it work — the form, the security token, and the input fields that connect back to your Application settings.

Overview

An authentication layer sits in front of secure content and asks recipients to verify who they are before they can view it. It's the page someone lands on after clicking a secure link in an email, and it gives them a simple form to confirm their identity using the factors you've nominated in your Application.

You'd use one whenever the content behind the link is sensitive — a personalised statement, a tax document, a policy update, anything containing personally identifiable information (PII). Rather than send the document itself, you send a secure link, and this landing page does the gatekeeping.

The page is just HTML, so you have full control over how it looks and behaves. What matters is that the form posts the right fields back to CX Platform, includes a security token, and handles failed attempts gracefully. We'll walk through each of those below.

How this connects to your Application
‍
The authentication factors recipients are asked for — surname, date of birth, postcode, account number, or anything else — are configured in the Security / data retention section of your Application. The field names on this page need to match what's set up there, otherwise the form won't validate. Get that lined up first, then build the page.

‍

What the page needs to include

There are a few non-negotiable parts to an authentication page. Everything else is styling.

Component What it does
Form with POST method The form has to submit using method="post" so the credentials are sent securely to CX Platform for validation. A GET request won't work.
XSRF token The line @Raw(Model.XsrfHtml()) renders a hidden anti-forgery token into the form. It's a security requirement — without it, the request will be rejected. Drop it inside the <form> tag, before your inputs.
Error message block The @if (!string.IsNullOrWhiteSpace(Model.ErrorMessage)) conditional shows a friendly message when someone enters the wrong details. Without it, failed attempts just refresh the page silently, which is a confusing experience.
Input fields One <input> per authentication factor, with a name attribute that matches the field configured in your Application's Security / data retention settings. Adding required stops empty submissions reaching the server.
Submit button A standard submit input — usually labelled Next or Verify — that posts the form back for validation.
Stylesheets and assets Linked CSS files in the <head> handle the visual styling. You can use the bundled CX Platform stylesheets or point at your own CDN to match your brand.

‍

Build the page

  1. Start with a standard HTML5 document — DOCTYPE, <head>, and <body> — and add the viewport meta tag so the page works on mobile.
  2. Link your stylesheets in the <head>. These CSS files and any other assets and resources can be added into your Application Asset Library.
  3. Wrap the page content in your container divs — a logo block, a header block with the page title and instructions, and a form block.
  4. Inside the form, drop in @Raw(Model.XsrfHtml()) as the very first thing. This is the security token — skip it and the form won't submit.
  5. Add the error message conditional next, so failed attempts surface a clear message rather than a silent reload.
  6. Add one input per authentication factor. The name attribute on each input has to match the field name configured in your Application — these names tell CX Platform which value to check against.
  7. Finish with a submit button. Use type="submit" and give it a clear label like Next or Verify.

‍

The full example HTML

Here's a working example. Swap the logo, stylesheet links, header copy, and input fields to match your brand and authentication factors:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Secure Document Verification</title>
  <meta content="width=device-width, initial-scale=1" name="viewport">
  <link href="path/to/your-brand.css" rel="stylesheet">
</head>
<body>
  <div class="page_wrapper">
    <div class="container_auth-wrapper">

      <!-- Logo -->
      <div class="card_logo-wrapper">
        <img src="path/to/logo.png" alt="" class="logo">
      </div>

      <!-- Header copy -->
      <div class="card_header-wrapper">
        <h1>Secure Document Verification</h1>
        <div>To access this document, please enter your details below and click 'Next'.</div>
      </div>

      <!-- Authentication form -->
      <div class="card_form-wrapper">
        <form method="post">

          <!-- Security token (required) -->
          @Raw(Model.XsrfHtml())

          <!-- Error message shown on failed attempt -->
          @if (!string.IsNullOrWhiteSpace(Model.ErrorMessage)) {
            <div class="error-message">
              <p>Those details are incorrect. Please try again.</p>
            </div>
          }

          <!-- Input fields — names must match Application config -->
          <div class="input-row">
            <label>Dealer Number</label>
            <input name="dealernumber" type="text" required>
          </div>
          <div class="input-row">
            <label>Zip Code</label>
            <input name="zip" type="text" required>
          </div>

          <!-- Submit -->
          <input class="btn-submit" type="submit" value="Next">

        </form>
      </div>

    </div>
  </div>
</body>
</html>

‍

Field names are case-sensitive
‍
The name attribute on each input has to match the field name in your Application exactly, including capitalisation. If your Application is configured for Surname and your input is named surname, the form will fail validation every time.

‍

Match the page to your brand

The structure stays the same across every authentication page — what changes is how it looks. A few common ways to make it your own:

Swap the logo by updating the <img> source in the card_logo-wrapper div. Use a hosted image so the logo loads reliably regardless of where the page is accessed from.

Adjust the header copy in the card_header-wrapper block to match the tone of the email that sent recipients there. A statement send might say "Verify your identity to view your statement", a policy update might say "Confirm your details to access your policy".

Style with your own CSS by replacing the linked stylesheets with your brand stylesheet. The class names in the example (page_wrapper, card_form-wrapper, btn-submit and so on) are just hooks — name them whatever fits your conventions.

‍

Test before you go live
‍
Always send a test email to yourself first and click through the secure link. Try the form with the correct details, then deliberately enter the wrong ones to confirm the error message displays the way you expect. A quick five-minute check beats finding out about a broken page after the send goes out.

‍

What's next

That's it — your authentication layer is built and ready to sit in front of secure content. Recipients clicking a secure link from this Application will land on your page, enter their details, and be granted access once the values match.

If you need to change which factors recipients are asked for, head back to the Security / data retention section of your Application. And if you're rolling this out across multiple Applications, save your HTML as a starting point — you'll only need to swap the input fields and branding for each one.