Skip to content

Email OTP Authentication for Dashboard Access

Overview

Users in the user_emails list can now authenticate to the dashboard using email OTP (One-Time Password) as an alternative to their regular organizational credentials (GitHub, Google, etc.).

Configuration

Enable/Disable Email OTP

In terraform.auto.tfvars:

# Users who can access the dashboard (same list)
user_emails = [
  "tautcius@gmail.com"
]

# Enable email OTP authentication
enable_email_otp = true

Who Can Use Email OTP?

Any email address in the user_emails list can authenticate using: 1. Primary method: Their configured organizational login (GitHub, Google, etc.) 2. Alternative method: Email OTP (requires email verification)

How It Works

Authentication Flow

  1. User visits dashboard: https://rpi-prod-1883c404a12f.tagai.uk (or similar)
  2. Cloudflare Access prompts for authentication
  3. User chooses one of:
  4. GitHub/Google Login (if configured)
  5. Email OTP: Receives one-time code via email, enters it
  6. Access is granted if user is in the user_emails list

Email OTP Details

  • Delivery: Sent directly to user's email
  • Validity: 10 minutes (Cloudflare default)
  • Resend: Available if code expires
  • No password: Purely email-based verification

Access Control

Admins (admin_emails)

  • Access: Node-RED UI, SSH, Dashboard
  • Authentication: GitHub + Organization Team
  • Email OTP: Not available (admins only)

Users (user_emails)

  • Access: Dashboard (read-only)
  • Authentication: GitHub/Google OR Email OTP
  • Node-RED UI: Not accessible (admin-only)

Terraform Configuration

Variables

variable "user_emails" {
  description = "User email addresses for Cloudflare Access"
  type        = list(string)
  default     = []
}

variable "enable_email_otp" {
  description = "Enable email OTP as authentication method for users"
  type        = bool
  default     = true
}

Module Setup

module "access" {
  source = "./modules/access"

  user_emails      = var.user_emails
  enable_email_otp = var.enable_email_otp
  # ... other variables
}

Policy Details

Dashboard Application Policy

When enable_email_otp = true:

Policy: Allow Users - Dashboard Access
├─ Include: Gaisro Technika Users group
├─ Require: Email OTP provider
└─ Decision: Allow

Users must be in the user_emails list and pass email OTP authentication.

When enable_email_otp = false:

Policy: Allow Users - Dashboard Access
├─ Include: Gaisro Technika Users group
└─ Decision: Allow

Users in the list are automatically granted access (no additional auth required if already logged in via GitHub/Google).

Use Cases

1. Guest Access

Add temporary users to user_emails:

user_emails = [
  "tautcius@gmail.com",
  "guest@example.com"  # Temporary guest with email OTP
]

Guest authenticates via email OTP without needing GitHub/Google account.

2. External Stakeholders

Partners/contractors who don't have organizational credentials:

user_emails = [
  "partner@example.com"
]

They use email OTP to access the dashboard for monitoring.

3. Passwordless Internal Users

Employees can use email instead of password manager:

user_emails = [
  "user@company.com"  # Can use email OTP OR company GitHub
]

Security Considerations

Strengths: - No password storage or reuse - Email-based verification is auditable - Time-limited (10 minutes) - Sent via secure email infrastructure - No third-party OAuth dependency

⚠️ Limitations: - Email interception possible (use company email) - Email account compromise = access compromise - Cannot enforce 2FA with email OTP alone - Requires valid email delivery

Deployment

Apply Changes

cd terraform/

# Validate configuration
terraform validate

# Plan changes
terraform plan

# Apply
terraform apply

Verify Configuration

# Check Access group created
terraform output | grep -i user

# Check policy created
cloudflare_zero_trust_access_policy.web_users

Testing

Test Email OTP Login

  1. Clear browser cookies/cache
  2. Visit dashboard URL: https://rpi-prod-1883c404a12f.tagai.uk
  3. Click "Email" option (if shown)
  4. Enter email: tautcius@gmail.com
  5. Check email for OTP code
  6. Enter code on Cloudflare Access page
  7. Should be redirected to dashboard

Test Regular Login (If Configured)

  1. Visit same URL
  2. Click "GitHub" or "Google" option
  3. Authenticate with organizational credentials
  4. Should be redirected to dashboard

Troubleshooting

Issue: "Email not recognized"

  • Cause: Email not in user_emails list
  • Fix: Add email to variable and reapply Terraform

Issue: "OTP code expired"

  • Cause: Took >10 minutes to use code
  • Fix: Request new OTP code from login page

Issue: "Email not received"

  • Cause: Spam filter, wrong email, or email service issue
  • Fix: Check spam folder, verify email address, contact admin

Issue: "Still can't login after adding to list"

  • Cause: Terraform not applied
  • Fix: Run terraform apply

Advanced Configuration

Require Email OTP + GitHub (MFA-style)

To require both email OTP AND GitHub authentication (stronger security):

# Modify the policy in access/main.tf
require = [{
  github = { ... }
}, {
  email_otp = { ... }
}]

This enforces multi-factor authentication.

Disable Email OTP

To turn off email OTP:

enable_email_otp = false

Then:

terraform apply

Users must use GitHub/Google to login.

Audit Trail

All email OTP authentications are logged in: - Cloudflare Logs: Access > Accounts > Activity - Filter: Look for "Email OTP" authentication events - Details: Email, IP, timestamp, success/failure

Best Practices

  1. Use company emails: Avoid personal/free emails for security
  2. Monitor access logs: Regularly review who's accessing
  3. Limit user list: Keep only necessary users
  4. Combine with policies: Use Access groups for fine-grained control
  5. Test before rollout: Test with pilot users first

Last Updated: January 7, 2026 Status: Ready for Deployment ✅