How Fineract accepts Keycloak-issued tokens
A Fineract deployment still on HTTP basic authentication with the default development login needs a central identity source before it goes near production. The supported route is to make Keycloak the OAuth2 provider and have Fineract accept the bearer tokens it issues. Fineract's README shows both OAuth2 and HTTP basic authentication, so the change is configuration and verification, not custom code. This section explains the moving parts; the sections that follow walk through the build steps.
The Fineract side of the pattern is a Keycloak realm, here named fineract in the project's walkthrough, containing a community-app client. That client uses client authentication and direct access grants, which lets the Mifos web app exchange a username and password for a token. A User Property mapper then writes the username into the token sub claim, because Fineract resolves the caller by that value. Confirm the claim name and mapper type against the current Fineract documentation for your release before you copy the walkthrough settings, since a mismatch produces valid tokens that Fineract still rejects.
This page covers three parts: the Fineract configuration that validates tokens, the Keycloak realm and client, and the Mifos web app login settings, which are disabled by default in the openMF/web-app repository. Each part should be tested separately. Check that a token issued for one tenant is rejected when the Fineract-Platform-TenantId header names another, and that the development mifos login no longer works. Decide early who owns realm administration, how client secrets are stored and rotated, and whether Keycloak will run in a cluster, because those choices shape the work more than the Fineract settings do.
What you need before configuring Keycloak and Fineract
Five things need to be in place before any realm or client is created: a supported Keycloak release, a supported database, a running Fineract 1.x instance with its tenant known, HTTPS on both services, and the ability to change environment variables. Each one changes what you configure later, so confirm them before the build starts.
A supported Keycloak release
Start from the current release, Keycloak 26.8.1, published October 13, 2026. If your organization uses the Red Hat build of Keycloak instead, its product page listed 26.6 as the latest version, so confirm which build your support contract covers before you pick a version. Keep the release you choose in your change record, because the upgrade path affects realm and client settings later.
A supported database for Keycloak
Keycloak needs a production database from its supported list, which includes PostgreSQL 14 to 18. The default development file database is for testing only. Keep Keycloak's database separate from the Fineract database, and confirm backup and restore for it, because realms, clients and user records live there and the Fineract login flow depends on them.
A running Fineract 1.x instance
Fineract 1.x is the maintained line, and 1.15.0 is the current stable release. Confirm that the instance starts, that the API responds, and that you know the tenant identifier you will send in the Fineract-Platform-TenantId header. Ask your team which tenant holds staff users, because the token subject must match a user that exists in that tenant.
HTTPS on Keycloak and Fineract
Both Keycloak and Fineract must be reachable over HTTPS at the addresses the token issuer, the web app and the redirect URIs will use. Fineract's documentation strongly encourages HTTPS only and documents SSL settings such as FINERACT_SERVER_SSL_ENABLED. Decide the public hostnames now, because changing an issuer URL later means updating every client and every consumer that validates tokens.
Access to change environment variables
Fineract's OAuth2 and SSL settings come from environment variables, so you need a way to set them per environment without rebuilding images. Confirm who owns the deployment manifests or Compose files, how secrets are injected, and how a change is rolled out and reverted. Remove the default development login of mifos before any shared environment is reachable.
Keycloak Operator prerequisites, if used
If you install Keycloak with the Keycloak Operator, use Operator Lifecycle Manager, which is the recommended installation method. Set the operator update approval to manual, because the operator documentation strongly recommends this to avoid unintended automatic upgrades. Agree who approves each operator update and when it is tested against your realm and client configuration.
Configuration sequence from realm to bearer token
This sequence takes a Keycloak instance from an empty realm to a verified bearer token that Fineract accepts for a tenant-scoped request. Each step ends with a check, so a failure is caught at the layer where it occurs.
Create the fineract realm
In the Keycloak admin console, create a dedicated realm named fineract so that Fineract users, clients and signing keys stay separate from other applications. The Keycloak administrator performs this step, and the platform team should record the issuer URL that Keycloak shows for the realm, because Fineract must trust exactly that issuer later. Check that the realm's OpenID Connect discovery document loads from the issuer URL and lists a token endpoint. If it does not, fix the hostname or proxy settings before going further.
Create the community-app client
Create an OpenID Connect client named community-app in the fineract realm, with client authentication turned on and direct access grants enabled. Direct access grants let a test script exchange a username and password for a token with a single request, which is how the Fineract walkthrough verifies the setup. Store the generated client secret in your secrets manager, not in a shared document. Check that the client's credentials tab shows a secret, and that the client appears in the realm's client list with the expected redirect settings for the Mifos web app.
Add the user property mapper for sub
On the community-app client, add a mapper of type User Property that copies the username field into the access token claim named sub. Fineract identifies the caller by this claim, so it must match the username that exists in the Fineract user table. Confirm the exact username format with your Fineract administrator, since usernames are case sensitive in the matching process and must agree on both sides. Check that a test user can request a token and that the decoded token's sub value equals the Fineract username, not a Keycloak internal user ID.
Set the Fineract OAuth2 environment variables
Configure the Fineract instance through its environment variables so that it validates bearer tokens from the fineract realm and stops accepting basic authentication for API users. The platform team sets the issuer URI, the realm's JWK set location and the HTTPS endpoints, and confirms the exact property names against the Fineract platform documentation for the release in use. Keep the Fineract basic authentication path in place until the checks in the next steps pass, so you can roll back. Check that the application starts without errors and that its logs show the OAuth2 resource server is active.
Request a token from Keycloak
Using the community-app client and a test user, call the realm's token endpoint with the password grant that direct access grants enable, and capture the access token from the response. Run this from a host that can reach Keycloak over HTTPS, and keep the test credentials out of shell history and build logs. Check the response for a 200 status and an access_token field. Then decode the token payload, without verifying it, to confirm that sub holds the username and that iss matches the issuer URL recorded in the first step.
Call a tenant-scoped endpoint with the bearer token
Send a GET request to a tenant-scoped Fineract endpoint, such as the clients list, with the Authorization header set to the bearer token and the Fineract-Platform-TenantId header set to the target tenant identifier. Run the same request with no token, and then with a token whose tenant header names a tenant the user cannot access. Check for 200 with the bearer token and the correct tenant, 401 without a token, and a refusal for the wrong tenant. If the authenticated call returns 401, compare the token issuer and sub with the Fineract settings from the previous step before changing anything else.
Confirm basic authentication is retired for API users
Once bearer calls behave as expected, confirm that basic authentication requests are rejected for the same users and endpoints, and record the result as the acceptance evidence for this configuration. The security owner should review the outcome and the client secret storage before the Mifos web app login is connected. Check that a request using basic credentials no longer succeeds on tenant-scoped endpoints, and that the test results and configuration values are saved with the change record.
How the username, tenant and roles map into Fineract
Fineract authenticates a bearer token by reading its subject, and it then matches that subject to a user account in the tenant. The Fineract walkthrough for Keycloak adds a User Property mapper to the client so the sub claim carries the username, which keeps the identity Fineract expects aligned with the name staff already know. Without this mapping, Keycloak's default subject is an internal user identifier that will not match any Fineract user record.
- Username in `sub`: Confirm the User Property mapper writes the Keycloak username into
sub, and that the mapper is attached to the client Fineract validates against. - Username uniqueness: Keycloak usernames must match Fineract usernames exactly, including case handling, so plan how renamed or duplicate staff accounts are reconciled before cutover.
- Audit attribution: Fineract records the acting user on changes, so the subject is the value your audit trail will show. Decide whether that is acceptable for your records policy.
- Service accounts: Machine clients need their own subject values and Fineract users, not shared staff identities.
- Claim names: The exact claim names Fineract reads should be verified against the Fineract version in use, not assumed from a tutorial written for another release.
Confirm the claim name and the resulting value by decoding a test token from your own realm before you configure any user records.
Fineract is multi-tenant. Each API request carries the Fineract-Platform-TenantId header, and the server uses that value to choose the tenant connection configured from the tenants database. The bearer token proves who the caller is, but the header decides which tenant's data the call touches, so the two must be checked together and never treated as interchangeable.
- Header on every call: Every API request, including those from the Mifos web app, must send the tenant header. A missing header is a configuration error to test for, not a default to rely on.
- Tenant membership: Confirm that the user account in the target tenant exists and is active. A valid token for one tenant does not grant access to another tenant's records.
- Tenants database: Tenant connections come from the tenants database, so changes to tenant definitions are infrastructure changes and should go through your normal change control.
- Gateway enforcement: If an API gateway sits in front of Fineract, decide whether it validates or rewrites the tenant header, and document who owns that rule.
- Multi-tenant testing: Test that a user in tenant A cannot read or write tenant B data by changing only the header.
Confirm the header name, the tenant identifiers and the failure response your Fineract version returns when the header is missing or wrong.
Keycloak handles authentication, but Fineract still holds its own user accounts, roles and permissions for each tenant. A Keycloak login therefore does not by itself give a person any Fineract permission. The practical question is how each Keycloak user or group corresponds to a Fineract user record and the roles assigned to it, and whether that link is maintained by hand or by a process.
- Two sources of truth: Keycloak controls who can sign in. Fineract controls what a signed-in user can do. Document both, and name the owner of each.
- Role assignment: Confirm whether your Fineract version maps token roles or groups to Fineract roles automatically, or whether roles must be assigned inside Fineract for each user.
- Provisioning and removal: Plan how a leaver is removed. Disabling the Keycloak user blocks sign-in, but the Fineract account and its permissions must also be deactivated.
- Segregation of duties: Approval and maker-checker permissions should be reviewed against your control matrix, since a broad Keycloak group can unintentionally grant those rights.
- Access reviews: Schedule reviews that compare Keycloak group membership with Fineract role assignments so drift is detected.
Whether any role mapping exists in your Fineract version is something to verify against its documentation and source before you design the process around it.
Most mapping problems come from assumptions about the version, the realm and the tenant setup rather than from the protocol itself. Before building, your team should confirm each identity value against the exact Fineract release, Keycloak release and Mifos web app build you plan to run. The Fineract documentation, the openMF web app repository and the Keycloak documentation each describe their own settings, and they change between releases.
- Versions: Record the Fineract, Keycloak and web app versions together, and verify claim names and settings against each one.
- Realm and client settings: Confirm the realm name, client type and grant types match the walkthrough you follow, and that the web app client is registered with the correct redirect URIs.
- Test users and tenants: Create test users in at least two tenants and verify token subjects, header handling and role outcomes before loading real staff.
- Default credentials: Confirm that the development login shipped with Fineract is disabled or changed in every environment.
- Token lifetime and TLS: Confirm token lifetimes, HTTPS enforcement and certificate trust between Keycloak, Fineract and the web app.
Record each confirmed value in your configuration baseline so the mapping can be re-verified after each upgrade.
Mapping Keycloak claims and headers to Fineract fields
This table compares each identity value in the Keycloak setup with the Fineract or Mifos web app setting it feeds. Read it as a checklist: every row names a value that must match exactly on both sides, and the final column shows which ones to confirm against the documented Fineract release before go-live.
| Mapping | Source value and destination | What to confirm |
|---|---|---|
| Username to token subject | Keycloak user username is carried into the sub claim through the User Property mapper on the community-app client | Confirm the sub claim value in a test token matches the username Fineract expects for staff login |
| Tenant header | Fineract-Platform-TenantId header selects the tenant whose connection is defined in the tenants database | Confirm the tenant identifier used in the header exists in the tenants database for the target environment |
| Client ID | community-app client ID in the Keycloak fineract realm must match the OAuth2 client configured for Fineract | Confirm the client ID, client authentication setting and direct access grants setting against the Fineract walkthrough for your release |
| Web app authorize and token URLs | MIFOS_OAUTH_SERVER_URL and the authorize and token endpoints point to the Keycloak fineract realm endpoints | Confirm the realm path and endpoint paths in your Keycloak version, since the web app README lists the settings but not every realm path |
| Web app redirect URL | Redirect setting in the Mifos web app must be registered as a valid redirect URI on the Keycloak client | Confirm the exact scheme, host and path, including HTTPS, match on both sides |
| Staff user records | Fineract staff user username should match the Keycloak username that appears in the token subject | Confirm how Fineract resolves the authenticated user to its staff record in your release, and test with a non-admin account |
| Default development login | The README default mifos login must not survive into a production deployment once OAuth2 is enabled | Confirm the default account is disabled or its password changed, and that basic authentication is no longer the only path |
Security settings that matter for this integration
Replacing basic authentication moves trust into Keycloak, the token flow and the web app login. The cards below cover the settings that decide whether that trust holds, from transport encryption and default credentials to secret handling and the Keycloak production configuration. Check each one in the environment you plan to run, not only in the development setup.
HTTPS only for Fineract
Bearer tokens and the tenant header travel with every API call, so plain HTTP exposes both. Fineract's documentation strongly encourages HTTPS only and configures SSL through environment variables such as FINERACT_SERVER_SSL_ENABLED. Confirm that the setting is enabled on every Fineract instance, including read and batch instances, and that the certificate chain is valid for the hostname the web app and clients use.
TLS on Keycloak endpoints
The authorize, token and userinfo endpoints must also be served over TLS, because authorization codes and access tokens pass through them. Keycloak's production guidance expects HTTPS for the server and recommends that the hostname and proxy settings match the public URL. Verify that the issuer URL in each token matches what Fineract and the web app expect, since a mismatch fails validation even when TLS works.
Replace the default mifos login
Fineract's README ships a development login of mifos with a default password, and the README states this must be changed for any real deployment. Change the credential before go-live, and remove or disable any test user that remains in the fineract realm. Once Keycloak is the provider, confirm that basic authentication is no longer offered on the public API path if your gateway allows that choice.
Confidential client secret handling
The community-app client uses client authentication, so its secret must stay on the server side, never in the browser bundle or a public repository. Rotate the secret after any suspected exposure and store it in a secrets manager or a Kubernetes secret with restricted read access. Check which services can read it, and confirm that the web app login does not expose the secret through build-time settings.
Keycloak production configuration
Keycloak's development mode and the default dev-file database are not suitable for production. Review the production configuration guidance for hostname, proxy headers, TLS, cache and database settings before the realm carries real users. Also plan Keycloak upgrades with manual operator approval and review the upgrading guide, since minor releases can change behavior and the Keycloak Operator docs recommend manual approval for operator updates.
Keep credentials out of source control
The Keycloak database credentials, the Keycloak admin account and the Fineract database connection details are all sensitive, and they often end up in Helm values, Compose files or realm exports. Keep them in an external secret store, reference them at runtime, and scan repositories for committed secrets. Exported realm files should also be reviewed before they are committed, because they can contain client secrets.
Keep web app login disabled by default
The openMF/web-app keeps OAuth2 login off by default through MIFOS_OAUTH_SERVER_ENABLED. Enable it only in an environment where the Keycloak redirect URIs, client ID and token endpoints are confirmed, and leave it off elsewhere so that a misconfigured build cannot fall back silently to an unintended login path. Record the flag value in the release checklist for each environment.
How to test OAuth2 login before basic authentication is turned off
Basic authentication should stay available until every OAuth2 path has passed its tests, so the test plan starts with token issuance for each test user. Create a test user for each role the Fineract deployment uses (teller, loan officer, branch manager, administrator), sign in through the fineract realm, and confirm that the access token's sub claim carries the username, as the User Property mapper was set up to do. Then call a read endpoint and a write endpoint with the bearer token and the Fineract-Platform-TenantId header, and confirm that each role gets the permissions its Fineract role grants and no more. Confirm the token lifetime and refresh behavior your Keycloak settings define, and record them, because the Mifos web app session depends on them.
Next, test the rejection paths. Submit an expired token, a token with an altered payload or signature, a token issued by a different realm or client, and a valid token with a wrong or missing tenant header. Each request should be refused, and the refusal should be logged on the Fineract side and the Keycloak side. For the Mifos web app, sign in, sign out, then press the browser back button and try a protected screen, and check whether the app clears its stored session and returns to the login page. Repeat after an administrator disables a test user in Keycloak to confirm that existing sessions end within the window you have configured. Confirm these behaviors in your own environment, since the exact session handling depends on the web app version you run.
Run basic authentication and OAuth2 in parallel for a defined period, with both paths logging the same business transactions. Compare outcomes for the same test cases on both paths and investigate every difference before switching off basic authentication. Keep a dated record of each test run, the software versions under test, the test accounts used, the configuration files and realm exports, and the failures with their resolution. This record supports internal review and change approval. It does not amount to an audit report or certification, so ask your assessor or compliance team which of these records they expect to see.
Why Fineract rejects Keycloak tokens and how to fix it
This table lists the failures teams most often hit when Fineract and the Mifos web app sit behind Keycloak, with the likely cause and the fix for each. Work through the rows in order when a login or API call fails, because the tenant header and token subject problems are usually checked first. Confirm each cause against your own realm, client and environment settings before changing anything.
| Symptom | Likely cause | Fix |
|---|---|---|
| 401 with a valid Keycloak token | The Fineract-Platform-TenantId header is missing or names the wrong tenant | Send the tenant identifier header on every call, and confirm it matches a tenant in the tenants database |
| Fineract rejects the token as unknown user | The sub claim carries a Keycloak internal ID, not the username, because the User Property mapper is absent | Add a User Property mapper to the community-app client so the sub claim carries the username, then request a new token |
| Mifos web app redirect loop at login | The redirect URI registered on the Keycloak client does not match the web app's redirect setting | Copy the exact redirect URI from the web app configuration into the client's valid redirect URIs, including scheme, host, port and path |
| Token issuer mismatch after a change | The Keycloak hostname, reverse proxy or TLS certificate changed, so the issuer in new tokens no longer matches the value Fineract expects | Set the issuer and token URLs in Fineract and the web app to the new public hostname, and confirm the TLS chain is trusted by the Fineract server |
| Login fails after a Keycloak upgrade | Client settings drifted during the upgrade, such as client authentication, direct access grants or mappers, or a changed default | Compare the client and mapper configuration with the documented walkthrough, reapply any missing settings, and test a token request before reopening access |
| Token request fails with client errors | Client secret rotated, or client authentication turned off for the community-app client | Confirm client authentication and direct access grants are enabled and that the secret in the calling configuration matches Keycloak |
| Mifos login button does not appear | Web app OAuth2 setting is still disabled, which is the default | Enable the OAuth2 server setting and supply the server URL, client ID and endpoint settings from the web app documentation |
Questions buyers ask about Fineract and Keycloak integration
How long does a Fineract and Keycloak OAuth2 integration take?
The duration depends on how many environments need the change, whether a Keycloak instance already exists, and how many clients, scripts and services currently send basic authentication to Fineract. A single development environment with a new realm and one client is a small piece of work, while production cutover across several environments with staged credential changes takes longer. No fixed duration applies to every estate. Ask for a timeline in the written scope, and ask which steps depend on your identity team's approval windows and change control.
Can our team integrate Keycloak with Fineract without outside help?
Yes, if your team has administrators who can run Keycloak and engineers who can configure Fineract's environment variables and test bearer token calls. The Fineract documentation includes a walkthrough that creates a fineract realm and a community-app client, and adds a User Property mapper so the token sub claim carries the username. The harder parts are usually not the clicks: they are client secret handling, token lifetimes, tenant header behavior across services, and the cutover plan for existing integrations. Outside help is most useful when those decisions need a written design and test evidence.
What does the integration need from our identity and infrastructure teams?
Expect the identity team to own the Keycloak realm, client registrations, user lifecycle, password and MFA policy, and token settings. The infrastructure team typically owns the hosts or cluster, DNS, TLS certificates, network paths between the Mifos web app, Fineract and Keycloak, and secret storage. Both teams need to agree on:
- The redirect URIs and allowed origins for each environment
- Who approves changes to client secrets and token lifetimes
- Where Keycloak runs and how its database is backed up
- How service accounts for batch or integration callers are created and rotated
What drives the cost of a Fineract Keycloak integration?
Cost follows the written scope, so the main drivers are the number of environments, the number of Fineract tenants and clients that authenticate, whether Keycloak is already deployed and hardened, and whether it must run in a highly available design. Involving the Mifos web app adds work for its OAuth2 settings, redirect configuration and login testing, which are disabled by default in its project documentation. One-time work includes design, configuration and testing. Recurring costs include Keycloak upgrades, certificate renewal and support. Ask each quote to separate these items and to state what the client provides, such as hosting, DNS and existing Keycloak access.
What should we ask for in a fixed-scope quote for this work?
Ask for a written scope that names each deliverable and the environments it covers. Useful items to request include:
- The realm and client configuration, with the mapper settings for the token subject
- How the tenant header is passed and validated for each tenant in use
- Whether the Mifos web app login is in scope, and which settings are changed
- Test cases for bearer token calls, failed logins and expired tokens
- The cutover and rollback plan for basic authentication
- Documentation handover and what the client must run after go-live
- Exclusions, such as Keycloak hosting, upgrades or high availability work
A quote that omits these items makes later changes hard to price fairly.
Does Keycloak high availability need synchronous database replication?
Yes. Keycloak's high availability documentation states that both supported multi-site designs need a synchronously replicated database. This applies to the single cluster design, which can span availability zones, and to the multi-cluster version 2 design that does not use an external Infinispan cluster. The deprecated multi-cluster version 1 design used a separate Infinispan cluster per site, and its requirements differ. Confirm with your database team which replication mode your PostgreSQL or other supported database offers, and test failover before relying on it for Fineract logins.
Which Keycloak version and database should we plan around?
Plan for the current Keycloak release supported by your chosen deployment method, and confirm it against the official release pages before you start. Keycloak supports several production databases, and PostgreSQL is the database Fineract recommends, which keeps your operational skills in one place. Keycloak migrates its schema automatically at startup by default, but larger deployments can apply migrations manually, as the upgrading guide suggests. Decide this before the first environment is built, and record the upgrade cadence so the identity and Fineract teams are upgrading against a known plan.
Keeping Keycloak upgrades from breaking the Fineract login
Treat every Keycloak upgrade as a change that can break the Fineract login, because the token issuer, the client settings and the sub mapping all sit upstream of Fineract. Keycloak has moved to a faster release rhythm: since Keycloak 26.0, the project plans four minor releases a year and a major release every two to three years, and it says breaking changes in a minor release will be opt-in. That makes opt-in behavior the key thing to confirm in each release note, and the upgrade plan should name who reads those notes and who approves the change before it reaches the realm that Fineract and the Mifos web app depend on. Review the backwards compatibility notes for every target version before you schedule the upgrade.
If you run the Keycloak Operator, set its update approval to manual. The Operator documentation strongly recommends this mode to avoid unintended automatic upgrades, so a new Keycloak version only rolls out when your team approves it. Schema migration runs automatically at startup by default. For a small deployment that is usually acceptable, but for a large database you should ask whether manual migration, where your administrators apply the SQL themselves, fits your change window better. Take a database backup before either path, and confirm the migration behavior against the upgrading guide for your version. Keycloak also exposes metrics that can feed your monitoring, so watch login failure rates and token endpoint errors during and after each rollout.
After every upgrade, re-run the token test from the setup steps: request a token for the Fineract client, confirm the sub claim still carries the username, and make one bearer call with the Fineract-Platform-TenantId header. Then confirm the Mifos web app can complete its OAuth2 login. Keep this test as a scripted check with a dedicated test user, so the result is repeatable and recorded in your change log. If the test fails, roll back the Keycloak version and the client or mapper change together, since a Fineract login problem often traces to a mapper or redirect setting that changed during the upgrade.
How DeployOpen scopes and delivers Fineract and Keycloak identity work
DeployOpen is a Chainscore Labs company that plans and implements self-hosted open-source platforms inside your own infrastructure. The cards below follow one engagement from written scope through realm design, build, testing, handover and optional retainers, so you can see what each stage produces and what to check before signing.
Fixed scope agreed in writing
Most engagements are fixed-scope, so the scope, deliverables and timeline are agreed in writing before any build work starts. For this integration, the written scope should name the Keycloak version, the number of realms, the Fineract tenants that will accept bearer tokens, the Mifos web app login path and the environments covered. A quote follows from that document, so ask for the assumptions list along with the price.
Realm, client and tenant design
Before configuration, the team decides how Keycloak realms, clients and roles map to Fineract tenants and staff accounts. The reference walkthrough uses a fineract realm and a community-app client with client authentication and direct access grants, but your design may need separate clients for the back office, the web app and integrations. Agree this design on paper first, because changing the token subject or client model later affects every consumer.
Implementation in your infrastructure
DeployOpen implements Keycloak and the Fineract changes inside your cloud accounts, data centers or air-gapped networks, under your change control. Keycloak's production database, high availability design and operator approach are decisions your team should review before build. Ask who holds the administrator credentials, where realm exports are stored and how the environments are promoted from test to production.
Testing against real login flows
Testing covers the flows staff actually use: token issuance, username in the sub claim, bearer calls carrying the Fineract-Platform-TenantId header, token expiry and refresh, and the web app login redirect. Negative tests should confirm that basic authentication is off where it should be and that the default development login is removed. Ask for the test cases and results to be delivered as part of the handover.
Documentation and handover
The handover package should describe the realm and client configuration, the mapper settings, the tenant and header rules, the secrets rotation procedure and the Keycloak upgrade path. Your team should be able to rebuild the configuration from the exported realm and the infrastructure code without relying on the people who built it. Ask for a walkthrough session and a runbook for the administrator console changes you will make after go-live.
Optional retainers for support and upgrades
After handover, ongoing support, Keycloak upgrades and continuous testing can be covered by a retainer rather than a new project each time. Keycloak ships minor releases several times a year, and minor-release breaking changes are opt-in, so upgrades still need planning and regression testing. Ask what a retainer covers, how upgrade windows are scheduled and who approves changes to the production realm.

