Skip to content

Conditional Access

Conditional access policies let you enforce dynamic, context-aware security requirements at authentication time. Policies evaluate conditions such as the user’s IP address, device trust level, risk score, group membership, and the application being accessed. Based on these conditions, VeraID can allow, deny, or require step-up MFA.

How conditional access works

  1. A user attempts to authenticate (via OIDC, SAML, or direct login).
  2. VeraID evaluates all active conditional access policies against the request context.
  3. Policies are evaluated in priority order. The first matching policy determines the outcome.
  4. If no policy matches, the default action is allow (configurable).

Creating policies

Via the admin UI

  1. Navigate to Settings > Conditional Access > Policies.
  2. Click Create Policy.
  3. Define the conditions and requirements.
  4. Set the policy to active or dry-run mode.
  5. Click Save.

Via the API

Terminal window
curl -X POST https://app.veraid.io/api/v1/conditional-access/policies \
-H "Authorization: Bearer kd_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Block access from untrusted networks",
"description": "Deny access to admin dashboard from IPs outside corporate network",
"priority": 10,
"status": "active",
"conditions": {
"applications": ["admin-dashboard"],
"ipAddresses": {
"exclude": ["203.0.113.0/24", "198.51.100.0/24"]
}
},
"action": "deny",
"denyMessage": "Access to the admin dashboard is restricted to the corporate network."
}'

IP-based policies

Restrict access based on the client’s IP address or network range.

Allow only corporate IPs

{
"name": "Corporate network only for production apps",
"priority": 10,
"conditions": {
"applications": ["production-api", "admin-dashboard"],
"ipAddresses": {
"exclude": [
"203.0.113.0/24",
"198.51.100.0/24",
"2001:db8::/32"
]
}
},
"action": "deny",
"denyMessage": "This application is only accessible from the corporate network."
}

Block known-bad IP ranges

{
"name": "Block known threat IPs",
"priority": 1,
"conditions": {
"ipAddresses": {
"include": [
"192.0.2.0/24",
"100.64.0.0/10"
]
}
},
"action": "deny",
"denyMessage": "Access denied due to security policy."
}

Named IP locations

Define reusable IP location sets to simplify policy management:

Terminal window
curl -X POST https://app.veraid.io/api/v1/conditional-access/named-locations \
-H "Authorization: Bearer kd_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Corporate Offices",
"type": "ip",
"ipRanges": [
"203.0.113.0/24",
"198.51.100.0/24",
"192.0.2.128/25"
],
"trusted": true
}'

Then reference them in policies:

{
"conditions": {
"namedLocations": {
"exclude": ["Corporate Offices"]
}
},
"action": "require_mfa"
}

Device trust

Evaluate the security posture of the device before granting access.

Device trust levels

LevelDescriptionRequirements
managedCorporate-managed device with MDM enrollmentMDM certificate present, compliant with MDM policies
compliantDevice meets security baselinesOS up to date, disk encryption enabled, firewall active
registeredDevice is known to VeraID but not fully managedDevice certificate present, user-registered
unknownUnrecognized deviceNo device certificate or registration

Device trust policy

{
"name": "Require managed device for sensitive apps",
"priority": 15,
"conditions": {
"applications": ["finance-portal", "hr-system"],
"deviceTrust": {
"exclude": ["managed", "compliant"]
}
},
"action": "deny",
"denyMessage": "This application requires a managed or compliant device. Please enroll your device with IT."
}

Device registration

Users can register devices at Profile > Devices > Register Device. Device attestation relies on platform-specific mechanisms:

  • macOS/iOS — DeviceCheck or App Attest
  • Windows — TPM-based attestation via Windows Hello for Business
  • Android — Play Integrity API
  • Linux — Client certificate enrollment

Risk-based step-up MFA

Require additional authentication when the request context indicates elevated risk.

Risk signals

VeraID computes a real-time risk score (0-100) for each authentication attempt based on:

SignalWeightDescription
Unusual locationHighLogin from a country or region the user has never accessed from
Impossible travelHighLogin from two geographically distant locations within a short time
Unknown deviceMediumDevice not previously seen for this user
Tor/VPN exit nodeMediumIP address associated with anonymizing proxies
Failed login attemptsMediumMultiple recent failed login attempts for this account
Off-hours accessLowLogin outside the user’s normal working hours
New applicationLowFirst time accessing this specific application

Risk-based policy

{
"name": "Step-up MFA for high-risk logins",
"priority": 5,
"conditions": {
"riskScore": {
"min": 70
}
},
"action": "require_mfa",
"mfaRequirements": {
"methods": ["webauthn", "totp"],
"maxSessionAge": "15m"
}
}

Risk thresholds

Risk LevelScore RangeDefault Action
Low0 - 30Allow
Medium31 - 69Allow (or require MFA, configurable)
High70 - 89Require step-up MFA
Critical90 - 100Deny (or require passkey + admin approval)

App-level policies

Apply conditional access policies to specific OIDC clients or SAML service providers.

Target by application

{
"name": "Restrict production API to platform team",
"priority": 20,
"conditions": {
"applications": ["production-api"],
"groups": {
"exclude": ["platform-team", "sre-team"]
}
},
"action": "deny",
"denyMessage": "Only platform and SRE team members can access the production API."
}

Target by application tag

Group applications using tags and target policies at the tag level:

{
"conditions": {
"applicationTags": ["tier-1", "production"],
"deviceTrust": {
"exclude": ["managed"]
}
},
"action": "require_mfa"
}

Dry-run simulation

Test policies before enforcing them by running in dry-run mode. In dry-run mode, policies are evaluated but not enforced. The evaluation result is logged for analysis.

Enabling dry-run

Terminal window
curl -X POST https://app.veraid.io/api/v1/conditional-access/policies \
-H "Authorization: Bearer kd_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Test: Require passkey for admin access",
"priority": 8,
"status": "dry_run",
"conditions": {
"roles": ["admin"],
"applications": ["admin-dashboard"]
},
"action": "require_mfa",
"mfaRequirements": {
"methods": ["webauthn"]
}
}'

Viewing dry-run results

Dry-run evaluations appear in the audit log with the conditional_access.dry_run event type:

Terminal window
curl -X GET "https://app.veraid.io/api/v1/audit-logs?eventType=conditional_access.dry_run&policyId=pol_abc123" \
-H "Authorization: Bearer kd_live_your_api_key"

Response:

{
"data": [
{
"eventType": "conditional_access.dry_run",
"timestamp": "2026-03-26T14:30:00Z",
"policyId": "pol_abc123",
"policyName": "Test: Require passkey for admin access",
"userId": "usr_def456",
"application": "admin-dashboard",
"context": {
"ipAddress": "203.0.113.42",
"deviceTrust": "compliant",
"riskScore": 15,
"authMethod": "password_totp"
},
"result": {
"wouldHaveAction": "require_mfa",
"wouldHaveRequired": ["webauthn"],
"actualOutcome": "allowed"
}
}
]
}

Simulation endpoint

Test a specific policy against a simulated request context without waiting for real traffic:

Terminal window
curl -X POST https://app.veraid.io/api/v1/conditional-access/simulate \
-H "Authorization: Bearer kd_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"userId": "usr_def456",
"application": "admin-dashboard",
"context": {
"ipAddress": "203.0.113.42",
"deviceTrust": "unknown",
"riskScore": 45
}
}'

Response:

{
"evaluatedPolicies": [
{
"policyId": "pol_abc123",
"policyName": "Block access from untrusted networks",
"matched": false,
"reason": "IP 203.0.113.42 is within allowed range 203.0.113.0/24"
},
{
"policyId": "pol_def456",
"policyName": "Require managed device for sensitive apps",
"matched": true,
"action": "deny",
"reason": "Device trust 'unknown' is not in allowed set [managed, compliant]"
}
],
"finalAction": "deny",
"denyMessage": "This application requires a managed or compliant device."
}

Policy evaluation order

Policies are evaluated in ascending priority order (lower numbers = higher priority). The first matching policy determines the outcome.

PriorityPolicyAction
1Block known threat IPsDeny
5Step-up MFA for high-risk loginsRequire MFA
10Corporate network only for productionDeny
15Managed device for sensitive appsDeny
20Platform team only for production APIDeny
100Default allowAllow

If no policy matches, the default action applies (configurable under Settings > Conditional Access > Default Action).


Next steps

Authentication Methods

Configure the authentication methods available for step-up MFA. Authentication Methods

Federation

Apply conditional access policies to federated login flows. Federation Guide

API Reference

Full API reference for conditional access endpoints. API Reference