Skip to main content

SSO (Single Sign-On)

ION Guard lets your organization use Single Sign-On via Microsoft Entra ID (formerly Azure AD), removing the need for local passwords for users and centralizing access management in your corporate directory.

The platform is built on a provider abstraction (SsoProviderContract) — Microsoft Entra ID is the natively supported provider, and the architecture accepts other OIDC providers (Google Workspace, Okta, Keycloak) with small code additions.

Navigation path: the Settings → SSO menu (route /settings/sso).

Required profile

Available to Tenant Admin or higher.

Multi-factor authentication (MFA)

ION Guard does not have its own second factor (TOTP). Multi-factor and conditional access policies are enforced by the identity provider (Microsoft Entra ID): when you enable SSO and disable password login for a user, all authentication — including MFA — becomes controlled by your corporate directory.


Prerequisites in the Azure Portal

Before configuring in ION Guard, prepare the following in the Azure Portal:

  1. An App Registration dedicated to ION Guard (Entra ID → App registrations → New registration), of the single tenant type (Accounts in this organizational directory only)
  2. The identifiers noted on the Overview tab:
    • Application (client) ID
    • Directory (tenant) ID
  3. A client secret created in Certificates & secrets — copy the Value right after creating it (it appears only once)
  4. The Redirect URI registered as type Web: https://<your-domain>/auth/sso/entraid/callback

The delegated Microsoft Graph permissions used by SSO are openid, profile, email, and User.Read — they usually come pre-configured on the App Registration.

tip

The exact callback URL appears on the ION Guard SSO configuration screen (the Redirect URI field, with a copy button). Copy it from there and paste it into the Azure Portal to avoid typos.


Configure the provider

On the Settings → SSO page, fill in the Microsoft Entra ID card:

FieldWhere to find it in Azure
Azure Tenant IDApp registration → Overview → Directory (tenant) ID
Application (client) IDApp registration → Overview → Application (client) ID
Client secretCertificates & secrets → the Value copied at creation
Enable this providerCheck the checkbox to activate

Click Save configuration. From that moment, the login screen shows the Sign in with Microsoft button.

All three fields are required on the first setup. Azure Tenant ID and Application (client) ID are validated as UUID; the Client secret requires at least 8 characters.

Do not paste the "Secret ID"

Azure shows two columns for each client secret: Value (the actual secret) and Secret ID (a UUID). Use the Value. Pasting the Secret ID causes error AADSTS7000215.

Secret rotation

When you need to rotate:

  1. Create a new client secret in the Azure Portal and copy the Value
  2. Paste it into the Client secret field in ION Guard and save
  3. Delete the old secret in Azure (after confirming the new one works)

Leaving the Client secret field blank preserves the stored value — useful for changing only Azure Tenant ID or Application (client) ID without rotating the secret. The secret is encrypted at rest and is never displayed again in the interface (the card only indicates that a secret is saved).


Enable SSO for users

By default, new users have SSO disabled. To grant SSO access to an existing user:

  1. Open the Users page
  2. Edit the user
  3. Under Login methods, check Login via SSO
  4. (Optional) Uncheck Password login to force them to use SSO only
  5. Save
Prior existence required

The user must already exist in ION Guard with the same email as in Entra ID. SSO does a passive match by email — there is no automatic account creation (JIT) on first login.

After the first SSO login, the oid (the immutable Entra ID Object ID) is saved as the link. From then on, even if the user's email changes in the directory, login keeps working.

Each user needs at least one login method

The Password login and Login via SSO flags are independent, but at least one must be active. The Platform Admin user always keeps password login enabled, as emergency access.


How the user signs in

With SSO configured and enabled for the user:

  1. The user opens the ION Guard login screen
  2. Clicks the Sign in with Microsoft button
  3. Is redirected to the Microsoft portal, where they authenticate normally (including MFA, if required by the directory)
  4. Returns to ION Guard already logged in, going straight to the dashboard

When both login methods are enabled, the user can choose: use the SSO button or fill in email/password just below the "or" divider.


Emergency access

Even with SSO active, the Platform Admin user always keeps local password access — it is the recovery mechanism in case the IdP becomes unavailable or the client secret expires.

For IdP downtime situations:

  1. The Platform Admin signs in through /login with a password
  2. Can temporarily disable the SSO provider in Settings → SSO by unchecking "Enable this provider"
  3. Users with only SSO enabled can have password login re-enabled individually on the Users page

Role mapping via App Roles

This is an optional and advanced capability. By default, each user's ION Guard role is managed locally in the panel. If you prefer to centralize role management in Entra ID (whoever is in group X automatically becomes Tenant Admin in ION Guard, without the panel operator needing to remember to update it), you can declare App Roles on your App Registration and map them to ION Guard roles.

Why App Roles and not groups

App Roles come as a roles claim directly in the identity token (with no extra call to Microsoft Graph), are managed in a dedicated UI in Azure, and are scoped to the application itself (they do not leak to other systems).

Declare App Roles in the manifest

In the Azure Portal: App registrations → ION Guard → Manifest. Locate the "appRoles" array (usually empty: "appRoles": []) and replace it with:

"appRoles": [
{
"allowedMemberTypes": ["User"],
"description": "Acesso total ao tenant ionguard.",
"displayName": "ionguard TenantMaster",
"id": "44005cb8-2ebb-48f0-bd23-2a6855771b20",
"isEnabled": true,
"origin": "Application",
"value": "ionguard.tenant_master"
},
{
"allowedMemberTypes": ["User"],
"description": "Gestão operacional do tenant (CRUD, alertas, usuários Operator/Viewer).",
"displayName": "ionguard TenantAdmin",
"id": "2c74b29d-4cab-466b-8909-4d9ad99760ba",
"isEnabled": true,
"origin": "Application",
"value": "ionguard.tenant_admin"
},
{
"allowedMemberTypes": ["User"],
"description": "Reconhecimento e resolução de alertas em sites atribuídos.",
"displayName": "ionguard Operator",
"id": "22a9792b-aede-4fa3-9350-cc361b948033",
"isEnabled": true,
"origin": "Application",
"value": "ionguard.operator"
},
{
"allowedMemberTypes": ["User"],
"description": "Acesso somente leitura em sites atribuídos.",
"displayName": "ionguard Viewer",
"id": "b702a6b4-8720-4b0e-8ce5-091edb78db16",
"isEnabled": true,
"origin": "Application",
"value": "ionguard.viewer"
}
]
Manifest details
  • Generate unique UUIDs for each id (do not reuse the ones from the example).
  • allowedMemberTypes accepts only "User" and/or "Application". Do not use "Group" (Azure rejects it with error Entitlement DirectAccessGrantTypes invalid). Groups can still be assigned to the role via the UI even with ["User"].
  • The value is what comes in the token — it can be any string, as long as it is consistent between Azure and the registration in ION Guard.
  • Do not declare a role mapped to Platform Admin — this role is never managed by SSO.

Click Save.

roles claim in the token

You do not need to add roles as an optional claim in Token configuration. The v2.0 endpoint of the Microsoft Identity Platform (used by ION Guard) automatically includes this claim when the user has App Roles assigned.

Assign users/groups to the App Roles

  1. Azure Portal → Enterprise applications (a different menu from App registrations)
  2. Select ION Guard
  3. Users and groups → Add user/group
  4. Choose users or groups → select the App Role → Assign

A single user can be granted more than one App Role — ION Guard chooses the one with the highest priority among those mapped.

Register the mappings in ION Guard

In Settings → SSO, scroll down to App Role mapping and add a row for each App Role declared in Azure:

App Role in AzureRole in ION GuardSuggested priority
ionguard.tenant_masterTenant Master40
ionguard.tenant_adminTenant Admin30
ionguard.operatorOperator20
ionguard.viewerViewer10

Each row requires the App Role in Azure (free text), the Role in ION Guard (Tenant Master, Tenant Admin, Operator, or Viewer — Platform Admin is not selectable), and a Priority (an integer from 0 to 10000). Higher priorities win in case of conflict, when a user has multiple App Roles.

Behavior at login

On each successful SSO login, ION Guard:

  1. Reads the roles claim from the identity token
  2. For each received App Role, looks up the corresponding mapping
  3. Applies the one with the highest priority
  4. Updates the local role and marks the user as managed by SSO

When the user is managed by SSO, the role select in the edit form is locked (except for Platform Admin) and the backend rejects manual role changes. To regain manual control:

  • Remove the user from the App Role in Azure; or
  • Disable SSO for that user in the panel

Edge cases: an SSO user with no App Role (or with an App Role that has no registered mapping) keeps their local role; the Platform Admin is never touched by the synchronization.

Azure propagation

App Role assignments in Enterprise applications can take a few minutes to appear in new tokens. If you just assigned it and the role did not sync, wait a few minutes and try logging in again.


Auditing

SSO events are recorded in the Audit Log (filter by action starting with sso.):

ActionWhen
sso.login_successUser successfully signed in via SSO
sso.config_createdFirst provider configuration
sso.config_updatedChange to the configuration
sso.role_mapping_savedMapping created or updated
sso.role_mapping_deletedMapping removed

Rejected login attempts (email not registered, SSO disabled for the user, etc.) do not generate an entry in the Audit Log — they go to the server log (storage/logs/laravel.log) with the prefix sso.login_rejected, since there is no valid associated user.


Troubleshooting

SymptomLikely cause
The "Sign in with Microsoft" button does not appear on the login screenProvider not enabled in Settings → SSO
Redirect to Azure gives AADSTS50011: redirect URI mismatchThe Redirect URI registered in Azure does not exactly match the one in ION Guard. Compare it with the URL in the Redirect URI field on the SSO card and adjust it under Authentication on the App Registration
AADSTS7000215: invalid client secretThe secret expired or was rotated in Azure but not updated in ION Guard. Create a new one in Azure and paste it into the panel
Login passes in Azure but returns to /login with no visible errorThe Azure email does not match any user in ION Guard, or the user exists but has Login via SSO unchecked. Check on the Users page
Role does not sync after assigning an App RoleAzure propagation can take a few minutes. Log out and log in after waiting. Also check that the mapping exists in Settings → SSO → App Role mapping with the exact value from the manifest
The Azure manifest returns Entitlement DirectAccessGrantTypes invalidallowedMemberTypes contains an invalid value (probably "Group"). Use only "User" and/or "Application"

Next steps

  • Users — Enable SSO and manage login methods per user
  • Access Profiles — ION Guard roles mapped by the App Roles
  • Auditing — Track sso.* events