Table of Contents

User Synchronization

Synchronization with the authentication server

Automatic user creation on the authentication server can be set up when a user is added to the cluster and does not already exist.

Important

The examples below are in the JSON format of the appsettings.json file. In a deployed environment, this configuration contains secrets (ClientSecretKey, PrivateKey, the SendGrid key...): set it as environment variables stored in Kubernetes secrets. See Configuration of the user synchronization for the environment variables of each authentication server.

Neos Auth

First, you need to add the following configuration:

{
  "UserPermissions": {
    "AuthProvider": "NeosAuth",
    "NeosAuth": {
      "Authority": "https://auth.neos.groupeisagri.com"
    }
  }
}

When a user is created on NeosAuth, the authentication server will send an email to the user with a link to set their password.

Microsoft Entra External ID

{
  "UserPermissions": {
    "AuthProvider": "MicrosoftEntraExternalID",
    "MicrosoftEntraExternalID": {
      "ClientId": "[CLIENT_ID]",
      "TenantId": "[TENANT_ID]",
      "TenantName": "[TENANT_NAME]",
      "ClientSecretKey": "[CLIENT_SECRET_KEY]"
    }
  }
}

When a user is created on Microsoft Entra External ID, the authentication server does not send any email to the user: the cluster sends them an email with a temporary password (see Temporary password email).

Okta

The Okta provider is supplied by the UserPermissionsOkta module, separate from UserPermissions so that the clusters which do not use Okta do not embed the Okta SDK. Reference it in addition to UserPermissions, with the same version:

ReferencedModules:
  UserPermissions: [NEOS_VERSION]
  UserPermissionsOkta: [NEOS_VERSION]

Then add the following configuration:

{
  "UserPermissions": {
    "AuthProvider": "Okta",
    "Okta": {
      "Domain": "https://[DOMAIN]",
      "ClientId": "[CLIENT_ID]",
      "PrivateKey": "[PRIVATE_KEY]",
      "KeyId": "[KEY_ID]",
      "GroupIds": ["[GROUP_ID]"],
      "ApplicationId": "[APPLICATION_ID]",
      "UseOktaActivationEmail": true
    }
  }
}
Property Required Default Description
Domain Yes URL of the Okta organization (for example https://xxx.okta.com).
ClientId Yes Client ID of the Okta API service application.
PrivateKey Yes RSA private key, in PEM format, used to sign the client assertion. Store it as a secret.
KeyId Yes Key ID (kid) of the public key registered in the Okta API service application.
GroupIds No [] Okta groups the users are added to.
ApplicationId No ID (0oa…) of the Okta application the users are assigned to: the cluster web application.
UseOktaActivationEmail No true Lets Okta send its activation email. When false, the cluster sends an email with a temporary password.

The login of the users is their email address.

Access to the Okta API

The cluster calls the Okta management API through the Okta .NET SDK, with the OAuth 2.0 client credentials flow, authenticated by a client assertion signed with a private key (private_key_jwt). In the Okta Admin Console:

  1. Under Applications > Applications, select Create App Integration, then choose API Services.
  2. In the Client Credentials section, choose Public key / Private key as the client authentication, then add a key: you can generate it in Okta and copy the private key in PEM format, or register your own public key. Copy the KID of the key.
  3. You can keep the Require Demonstrating Proof of Possession (DPoP) header in token requests option enabled: the cluster detects it and binds its access tokens to a DPoP proof.
  4. In the Okta API Scopes tab, grant the scopes required by the configuration:
Configuration Scopes
Always okta.users.read, okta.users.manage
GroupIds is not empty okta.groups.read, okta.groups.manage
ApplicationId is not empty okta.apps.read, okta.apps.manage
  1. In the Admin roles tab, assign an admin role allowing to manage the users, and the groups or the application used for the assignment.
Note

The Okta SDK also reads its own configuration sources (~/.okta/okta.yaml, an okta.yaml file in the application directory and the OKTA_CLIENT_* environment variables), which can be used to adjust settings such as the timeouts or the number of retries. The values defined in the UserPermissions:Okta section take precedence.

Access of the users to the cluster

A user created in Okta can only sign in to the cluster if they have access to the cluster web application. Depending on how this access is managed in Okta:

  • Groups: set GroupIds with the groups assigned to the cluster web application. The users are added to these groups.
  • Direct assignment: set ApplicationId with the identifier of the cluster web application, displayed in its URL in the Admin Console (it is also its Client ID, unless another one was set through the Okta API). The users are assigned to it.
  • No assignment: leave GroupIds and ApplicationId empty when the cluster web application is assigned to everyone, or when the access is managed by Okta rules.

GroupIds and ApplicationId can be combined.

The users are identified by their email address: when an Okta account already has the email address of the user (for example an employee managed by the organization, even if their Okta login is different), no account is created but the existing one is added to the groups and assigned to the application. The synchronization of the user fails when several Okta accounts have this email address, or, when no Okta account has it, when an Okta account has the login of the user with another email address, since it may belong to another person.

To sign in, the users must be identified by their email address: see the UserPropertiesMap of the Okta authentication.

The list of users that can be imported from Okta is limited to the users assigned to the application when ApplicationId is set, otherwise to the members of the groups when GroupIds is set, otherwise it contains all the users of the organization.

First password

  • When UseOktaActivationEmail is true, the user is created without password and Okta sends its activation email, so that the user sets their password. The cluster does not send any email and SendTemporaryPasswordEmail is ignored.
  • When UseOktaActivationEmail is false, the user is created with a temporary password, which they must change at first login, and the cluster sends it by email (see Temporary password email). The temporary password has 16 characters (lowercase and uppercase letters, digits and special characters): if the password policy of the Okta organization is stricter, keep UseOktaActivationEmail set to true.

Azure AD B2C

Warning

No longer recommended and replaced by Microsoft Entra External ID. Will be retired in May 2030.

First, you need to add the following configuration:

{
  "UserPermissions": {
    "AuthProvider": "AzureAdB2C",
    "AzureAdB2C": {
      "ClientId": "[CLIENT_ID]",
      "TenantId": "[TENANT_ID]",
      "TenantName": "[TENANT_NAME]",
      "ClientSecretKey": "[CLIENT_SECRET_KEY]",
      "B2cExtensionAppClientId": "[EXTENSION_APP_CLIENT_ID]"
    }
  }
}

When a user is created on Azure AD B2C, the authentication server does not send any email to the user: the cluster sends them an email with a temporary password (see Temporary password email).

Temporary password email

With Microsoft Entra External ID, Azure AD B2C, and Okta when UseOktaActivationEmail is false, the cluster creates the users with a temporary password and sends it to them by email.

The cluster uses SendGrid to send emails, which must be configured:

{
  "UserPermissions": {
    // ...
  },
  "SendGrid": {
    "Key": "[KEY]",
    "From": {
      "Name": "Neos",
      "Address": "[email protected]"
    }
  }
}
Note

You can disable invitation email sending by setting the SendTemporaryPasswordEmail property to false.

Email template

You can customize the email sending process and the generation of the template by overriding the following server methods in one of your modules:

  • GetAuthTemporaryPasswordEmailBodyTemplate: This method retrieves the template for the email sent to the user with their temporary password.
  • SendAuthTemporaryPasswordEmail: This method sends the email and makes an internal call to GetAuthTemporaryPasswordEmailBodyTemplate to retrieve the template.

Email content

The email template is defined in the server methods. The content of the email configuration is stored in either environment variables or the appsettings files.

{
  "UserPermissions": {
    "AuthProvider": "MicrosoftEntraExternalID",
    "MicrosoftEntraExternalID": {
      // ...
    },
    "EmailContent": {
      "RedirectUrl": "<cluster-url>",
      "Title": "Welcome !",
      "Content1": "You are invited to log in to our application using your email address (<strong>{Email}</strong>) and your temporary password, below, which you will have to change the first time you log in.",
      "Content2": "Your temporary password: <strong>{Password}</strong>.",
      "LinkText": "Access to application"
    }
  }
}

The contents can use the {Email}, {FirstName}, {LastName} and {Password} placeholders, replaced with the values of the created user. With the default template, the temporary password must appear in one of them ({Password} is in Content2 by default): otherwise the user does not receive it.

Synchronization between clusters

For ease of administration, if multiple clusters use the UserPermissions module, user information (such as creation, modification, or deletion) will be synchronized automatically across clusters. This synchronization ensures that changes made in one cluster are propagated to all other clusters.

Flow diagram

The diagram below illustrates the communication process between the authentication server and the business clusters when a user is created, modified, or deleted:

graph TD
    I["Identity provider<br>e.g. Azure AD B2C"]
    P["Pub/Sub<br>'UserAccountSaved'"]
    C1["Business Cluster 1<br>with 'UserPermissions'"]
    C2["Business Cluster 2<br>with 'UserPermissions'"]
    CN["Business Cluster N<br>with 'UserPermissions'"]
    T[Tenant Management]

    C1 -- "(1) RegisterUser on 'Saved'" --> I
    C1 -- "(2) Publish on 'Saved'" --> P
    P -- "Tenant Management<br>UpsertUserAccounts" --> T
    P -- "UserPermissions<br>UpsertUserAccounts" --> C2
    P -- "UserPermissions<br>UpsertUserAccounts" --> CN