Connect Microsoft Entra ID

Out of the box a DocuWare Ivy installation has no workflow users — a licensed engine deploys none. Connecting Microsoft Entra ID as an identity provider is how users and their roles get in, and how they sign in.

Both products, one sign-in

DocuWare and DocuWare Ivy each federate to Entra ID on their own. They are not connected to each other, and they do not need to be: Entra is the single sign-on point. A user who has signed in to DocuWare already has an Entra session, so when they open Ivy, Entra recognises that session and returns without asking for credentials again.

That means two app registrations, one per product, and they want quite different things:

DocuWare Ivy

DocuWare

Redirect URI

https://<public-host>/ivy/oauth2/callback

the callback URL shown in DocuWare's own security configuration

Extra setting

—

ID tokens must be activated

Graph permission

Directory.Read.All, application, admin consent granted

User.Read, delegated, granted

Client secret

required

optional

Covers

sign-in and importing users and roles

sign-in only

Configured in

config/ivy.yaml or the Engine Cockpit

DocuWare Configurations ‣ General ‣ Security

Note

Note

The asymmetry in the last two rows is worth planning around. Ivy's identity provider creates, updates and deactivates users from the group you point it at. DocuWare's Entra connection signs users in but does not synchronise them — it can auto-link an account that already exists, by matching user name and e-mail. So "import a group from Entra" applies to Ivy; on the DocuWare side the users have to get there another way.

The platform documentation already covers the generic part: what the provider does, the configuration reference, and the 19 steps to register the application in the Azure portal, with screenshots. Read those first:

This page is only what differs in a DocuWare Ivy on-premises installation.

The redirect URI is not what you would guess

The platform documentation gives the pattern as https://{host}/oauth2/callback. Here the engine serves everything under the /ivy prefix, so the value to register is:

https://<public-host>/ivy/oauth2/callback

Entra compares it literally: scheme, host, port and path all have to match.

Tip

Important

The engine builds this address from the incoming request, not from BaseUrl. Behind IIS that means the proxy has to pass the public host name and the HTTPS scheme through, and must not rewrite the redirect back to Entra. All of it is handled by the setup in Publish through IIS; if sign-in fails with an address mismatch, that page is where to look.

To read the value off an installation before a tenant exists: configure the provider with a made-up tenant and client id, request /ivy/docuware/oauth2/init/security?idp=microsoft-entra-id, and read the Location header of the 302. Nothing is sent to Entra by doing so.

What to ask for when registering the application

Item

Value

Platform

Web

Redirect URI

https://<public-host>/ivy/oauth2/callback

API permission

Microsoft Graph, application permission Directory.Read.All, with Grant admin consent

Needed afterwards

Directory (tenant) ID, Application (client) ID, and the value of a client secret

Note

Note

Directory.Read.All reads the whole directory, not just the group you intend to import. That is the permission the platform documentation asks for, and it is worth raising with whoever owns the tenant before the request goes in — it is the reason a non-productive tenant is usually preferred for testing.

Configure the engine

Add this to config/ivy.yaml and restart. The five keys below are the minimum; the platform reference lists the rest, including group-to-role mapping and attribute mapping.

Listing 12 config/ivy.yaml
SecuritySystems:
  docuware:
    IdentityProvider:
      Name: microsoft-entra-id
      Config:
        TenantId: <directory-tenant-id>
        ClientId: <application-client-id>
        ClientSecret: "${encrypt:the-secret-value}"
        GroupFilter: <object-id-of-the-group-to-import>
        Roles:
          Employee: <object-id-of-a-group>

Wrap the secret in ${encrypt:…} and the engine replaces it with an encrypted value the first time it reads the file, so the clear text does not stay on disk.

Tip

Important

It has to be docuware, not default. The branded portal lives in the docuware security context, so that is the security system whose users sign in. Configured under default, the engine accepts the settings and the portal's login page simply shows no Entra option.

Confirm the engine accepted the settings:

grep -iE 'identityprovider|securitysystem' logs/config.log

Each setting appears with its old value, its new value and its source. A key missing from that output did not arrive.

After a restart the portal's login page offers Entra ID as a second way in, alongside the local login. It points at /ivy/docuware/oauth2/init/security?idp=microsoft-entra-id, which is what starts the flow.

Who creates the users

The identity provider above signs people in. It does not, by itself, put anyone into Ivy — that is UserSynch, and it is the part most easily missed:

Listing 13 config/ivy.yaml, inside the same security system
SecuritySystems:
  docuware:
    UserSynch:
      OnLogin: true
      OnSchedule:
        Enabled: true
        Cron: "0 3 * * *"
        ImportUsers: true

ImportUsers is what creates accounts that do not exist yet, from the group in GroupFilter. OnLogin keeps a user's name, language and roles in step when they sign in.

The report is in its own log, not in ivy.log:

docker compose exec ivy cat logs/usersynch.log

You should see, for a group with one member:

Start synchronizing users of security system 'docuware'
1 users were read
1 users were analyzed
1 users were imported
0 users were disabled
0 users were updated
1 users were added to a role

Those counters are the whole verification: they prove the client secret works, the admin consent was granted, GroupFilter reads that group rather than the directory, and the role mapping applies.

Tip

Important

The Ivy role has to exist before the mapping can fill it

Roles: maps an Entra group onto a role the application already defines. Naming one that does not exist is silent: the import succeeds and the report says 0 users were added to a role.

The branded portal defines AXONIVY_PORTAL_ADMIN and Everybody. Create any other role in the Engine Cockpit first.

Note
Triggering a synchronisation without waiting for the schedule

Set the cron a couple of minutes out, restart, and watch logs/usersynch.log:

Cron: "*/2 * * * *"

Then put the real value back. This runs the same code path as the nightly job, which is what you want to test.

Skipping Ivy's own login page

With the identity provider configured, Ivy's login page gains Entra ID as a second way in, next to the local login. There is no setting to make that the default — but the option is a plain URL, and it takes the page to return to afterwards:

/ivy/docuware/oauth2/init/security?idp=microsoft-entra-id&originalUrl=<target>

Link users into Ivy with that and they never see the login page: the browser goes to Entra, Entra recognises the session from DocuWare, and they land on the target page. No proxy component and no extra infrastructure involved.

The DocuWare side

For completeness, since one Entra tenant serves both. The DocuWare Knowledge Center covers it in full at Connect to Microsoft Entra; in short:

  1. Create a second app registration, and add the callback URL from DocuWare's security configuration as a redirect URI with ID tokens activated.

  2. Give it Microsoft.Graph → User.Read delegated, with Granted status.

  3. Copy the Application (client) ID and the OpenID Connect metadata document URL from the app's endpoints.

  4. In DocuWare Configurations ‣ General ‣ Security, enable single sign-on and enter those two as Client ID and Issuer URL.

A client secret is optional there, for a higher security level. Automatic linking of existing DocuWare users works when user name and e-mail address match.

Keeping the sign-in proxy in front

Everything above works on the installation as Install DocuWare Ivy leaves it: the engine publishes its own port and Ivy does the Entra sign-in itself. Nothing more is needed.

You can also run the same configuration behind the sign-in proxy, which is what Sign in with DocuWare uses. In this mode the proxy authenticates nobody — one route, anonymous, forwarded straight through — so Entra sign-in behaves exactly as above. What it buys is the engine publishing no port at all, the proxy taking the port instead, and every installation having the same shape whichever identity source a customer has. IIS needs no change either way, because the port does not move.

To switch, set the mode in .env and bring the stack up with both files:

IVY_SSO_MODE=entra
docker compose -f docker-compose.yml -f compose.sso.yml up -d

The extra files this needs are the ones listed in Sign in with DocuWare — copy them across first, they are not part of the four the install guide sends.

Tip

Important

IVY_SSO_CLIENT_SECRET must still hold some value, even though nothing reads it here. Left unset it arrives as an empty string, overrides the configuration file and puts the proxy in a restart loop. Any non-empty value does.

The one thing this mode does not give you is a sign-out address: the proxy maps its logout endpoint only when it is doing the signing in. See below.

Signing out

There is no clean sign-out. Worth knowing before users ask.

The portal's logout ends the Ivy session, but it does not end the session at Entra ID. So the next visit is signed straight back in without a prompt, which looks as though logging out did nothing. The engine offers no way to change this: it has no sign-out address of its own, and the identity provider configuration has no post-logout setting.

Two consequences to plan around:

  • On a shared machine, closing the browser is the only reliable way to end a session. Tell users that, rather than letting them trust the button.

  • The portal can hide its logout entry if a control that appears to do nothing is worse than no control. It is a Portal variable, set per application:

    Variables:
      Portal:
        UserMenu:
          HideLogoutMenu: "true"
    

Sign in with DocuWare is better off here: that topology has a working sign-out address, because the sign-in proxy owns the session and can end it.

Single sign-on is a separate feature

Signing in with an Entra account is what the identity provider above does. True single sign-on — arriving already authenticated, with no second login — is a different mechanism, and it is not part of this guide.

DocuWare Ivy does not enable it, and the sample IIS script does not configure it. If a customer asks for it, raise it with DocuWare rather than enabling it from this page.

The link in the previous section is the practical middle ground: users who are already signed in to Entra reach the portal without seeing a login page, and nothing extra has to be installed.