Skip to main content

Access Control

OpenInsure uses Cloudflare Zero Trust Access with Microsoft Entra ID (Azure AD) for authentication across all portals and internal tools. Every application is gated by CF Access with per-app Azure AD security groups.

Architecture

User → Cloudflare Access (SSO wall) → Azure AD (Microsoft login) → App
                                    ↳ Group membership check (oi-* groups)
                                    ↳ Session cookie (30-day TTL)

Azure AD Groups

Each portal has its own Azure AD security group. Users must be in the correct group to access that portal. The oi-staff group is an umbrella that grants access to all portals.
GroupObject IDPurposeMembers
oi-staffa7e6f605-fccc-41ef-8250-d2dc7d741d1dAll internal staff (umbrella)15
oi-uw9bc58c75-476e-472f-a4ea-3c8a297d06a8Underwriting workbench5
oi-admin46a2a4c2-69a2-41d8-a6b4-d924ff5b2406Admin dashboard6
oi-workbench459e01c5-4d7c-4f0d-97cd-27e2bc734862Ops workbench6
oi-producer597cbbc6-1c06-4948-8cd6-ce14c40a4dc8Producer portal7
oi-carrier1bf106a7-c84c-4af2-8cab-a250825966d4Carrier portal4
oi-portal9d669306-28a2-4c15-85ae-a6e9e92f8accPolicyholder portal15
oi-finance76ef7c38-4e71-49b2-a5a5-f32a1a92c471Finance portal3
oi-compliance838ec16e-67c0-41dd-a645-c452718e7068Compliance portal4

CF Access Policy Structure

Every CF Access application has three policies in order:
  1. Allow [per-app group] — e.g., oi-uw for the UW workbench
  2. Allow oi-staff — umbrella fallback so leadership always has access
  3. Deny all others — blocks everyone not in a matching group
Tip: CF Access evaluates Service Auth and Bypass policies first, then Allow/Deny in order. The first matching Allow wins.

Portal → Group Mapping

PortalDomainGroupFallback
UW Workbenchuw-dev.openinsure.devoi-uwoi-staff
Adminadmin-dev.openinsure.devoi-adminoi-staff
Ops Workbenchworkbench-dev.openinsure.devoi-workbenchoi-staff
Carrier Portalcarrier-dev.openinsure.devoi-carrieroi-staff
Producer Portalproducer-dev.openinsure.devoi-produceroi-staff
Policyholder Portalportal-dev.openinsure.devoi-portaloi-staff
Finance Portalfinance-dev.openinsure.devoi-financeoi-staff
Compliance Portalcompliance-dev.openinsure.devoi-complianceoi-staff
Starlight Docsdocs.openinsure.devoi-staff
HQ Docs Hubmhchq.aioi-staff

Managing Users

Add a user to a portal

# Find the user
az ad user show --id "name@mhcmga.com" --query "{name:displayName,id:id}" -o table

# Add to group
az ad group member add --group "oi-uw" --member-id "<user-object-id>"

Add a user to all portals (staff)

az ad group member add --group "oi-staff" --member-id "<user-object-id>"

List group members

az ad group member list --group "oi-staff" --query "[].{name:displayName,email:mail}" -o table

Audit all groups

for group in oi-staff oi-uw oi-admin oi-workbench oi-producer oi-carrier oi-portal oi-finance oi-compliance; do
  echo "── $group ──"
  az ad group member list --group "$group" --query "[].displayName" -o tsv | sort
  echo ""
done

Duplicate Accounts

Some users have accounts under multiple domains (@palmettoconsulting.us and @mhcmga.com). Both accounts are added to the same groups so access works regardless of which account they sign in with.

Service Tokens (E2E Testing)

A CF Access service token e2e-test-bot exists for automated testing:
  • Client ID: 75e59720187743b9fed0a9cda9810172.access
  • Client Secret: stored in 1Password
To use in requests:
curl -H "CF-Access-Client-Id: <client-id>" \
     -H "CF-Access-Client-Secret: <client-secret>" \
     https://uw-dev.openinsure.dev/api/endpoint
Requires a Service Auth policy on the target Access application.

Terraform

All Access policies are managed in infra/terraform/access.tf. Group IDs are in infra/terraform/terraform.tfvars.
cd infra/terraform
export AWS_ACCESS_KEY_ID="<r2-access-key>"
export AWS_SECRET_ACCESS_KEY="<r2-secret-key>"
export CLOUDFLARE_API_TOKEN="<cf-api-token>"
terraform plan -var-file=terraform.tfvars
terraform apply -var-file=terraform.tfvars

Azure AD Tenant

  • Tenant: palmettoconsulting.onmicrosoft.com
  • Tenant ID: ebd58a52-c818-4230-b150-348ae1e17975
  • Domains: @mhcis.com, @mhcmga.com, @palmettoconsulting.us
  • Conditional Access: MFA enforced for all users

App Registrations

AppIDPurpose
OpenInsure Auth790becb2-6ec9-48bd-9a16-3b60861511d7Internal auth (magic link, JWT)
Cloudflare Access6a97e678-dfa7-441a-9a57-49602b53fc29CF Access SSO integration
Cloudflare Zero Trustbe6c7cd4-57be-425b-978d-c55f5dad217dAccount-level ZT integration

Force Logout

To force a user to re-authenticate (clears cached identity):
https://mhcis.cloudflareaccess.com/cdn-cgi/access/logout