Skip to content

Upgrading from rc.11 to rc.12

This page lists what you must change, and what behaves differently, when you move a HelixIAM install from v1.0.0-rc.11 to v1.0.0-rc.12. The source is the rc.12 release notes and the security review (findings H4 and H5).

What rc.12 is

rc.12 adds bring-your-own realm signing keys and certificates, with ES256 alongside RS256. It also closes two admin privilege findings (H4 and H5) and protects everything administrators sign in through. Most of the changes below tighten who may do what. One adds a start-up report for you to review.

Before you upgrade: checklist

# Do this Applies if
1 Optionally run the pre-upgrade query to see which administrators sign in through an external identity provider you use identity providers
2 After the upgrade, review the start-up report, confirm the AMBIGUOUS links that are right and revoke trust in any link you do not recognise the report lists anyone
3 Tell administrators that new links are made from the account console administrators sign in through an identity provider
4 Give realm-admin to the people who do the actions listed there you delegate administration with narrower permissions
5 Review realm keys and signing before you activate an ES256 key you plan to bring your own key or use ES256
6 Nothing to do for Flyway V86: it is applied automatically on start-up always (informational)

1. Administrators who sign in through an identity provider

What changed. Each federated link now records how it was made. An administrator signs in through a link only when the link is trusted:

Provenance Meaning Signs in an administrator
LEGACY existed before the upgrade yes
JIT the sign-in created the account yes
SELF linked by the user from the account console yes
WALLET an EU Digital Identity Wallet linked from the account console yes
ADMIN_CONFIRMED confirmed by a realm admin yes
AUTO matched by a verified e-mail address, or trust revoked no

Links belong to a realm. A link now signs its user in only in the realm it belongs to. V86 places each existing link in the realm whose identity provider has that alias. If the alias is used in several realms, or the provider comes from the realm config folder (which the migration cannot see), it holds the link as UNRESOLVED and logs how many there are. At the first start, after the realm config folder is loaded, each such link is resolved:

  • The alias now belongs to exactly one realm: the link moves there and keeps working (LEGACY). This is audited as LEGACY_LINK_RESOLVED.
  • No stored provider has the alias, and exactly one static helix.federation.* provider does (it serves every realm): the link stays in the user's home realm and keeps working (LEGACY), audited the same way.
  • Anything else (the alias is stored in several realms, a stored and a static provider share it, or the definitions differ): the link goes to the user's home realm and becomes AUTO. It still works for ordinary users, but it signs no administrator in until a realm admin confirms it. It is reported as AMBIGUOUS (see the next section). A link the migration cannot place at all signs no one in and is logged at start-up; the user links the provider again.

No lockout. Every link that exists at the upgrade becomes LEGACY and keeps working as it did in rc.11. Wallet links become WALLET. The attack these links were open to, a lower admin pointing the identity provider at their own issuer, now needs the linked administrators' own permissions.

To check in advance (optional). Run this on the rc.11 database. It lists every user who holds the admin role, or a role with admin permissions, and has a federated link:

SELECT DISTINCT r.tenant_id AS realm, u.username, f.idp_alias
  FROM federated_link f
  JOIN user_credentials u ON u.user_id = f.user_id
  JOIN user_in_role ur    ON ur.user_id = f.user_id
  JOIN user_roles r       ON r.role_id = ur.role_id
 WHERE r.name = 'admin'
    OR EXISTS (SELECT 1 FROM admin_role_permission p WHERE p.role_id = r.role_id)
 ORDER BY realm, u.username, f.idp_alias;

Admin permissions that come through a group (user_group_member and user_group_role) are not in this query. The start-up report below includes them.

What changed. At every start, the server reports each user who is an administrator in any realm (or in master) and has one of these links:

  • a LEGACY link (it still signs them in): a WARN and a PRIVILEGED_LEGACY_LINK audit event;
  • an AMBIGUOUS link (it signs them in only after a realm admin confirms it): a WARN and a PRIVILEGED_AMBIGUOUS_LINK audit event.

Each entry names the realm of the link, the username, the identity provider and the realms where the user is an administrator. The report never blocks anything.

What you must do. Review the report. In the console: Events, filter on type PRIVILEGED_LEGACY_LINK. Over the API: GET /admin/realms/{realm}/events?type=PRIVILEGED_LEGACY_LINK. For each entry, confirm that the account at the identity provider belongs to that administrator. Confirm an AMBIGUOUS link that is theirs (see the next section). If you are unsure about a LEGACY link, revoke trust in it:

  • Console: Users → (user) → Linked identities → Revoke trust.
  • API: POST /admin/realms/{realm}/users/{userId}/federated-identities/{alias}/revoke-trust with body {"externalSubject": "…"}. A user can have several links to one provider, so each request names one link.

Revoking trust needs realm-admin, and the user's admin permissions in every other realm they belong to (so only a master admin can act on a master admin's link). It is audited as FEDERATED_LINK_TRUST_REVOKED. The link then counts as AUTO: it still signs in an ordinary user, but never an administrator. The administrator can link the provider again themselves (see the next section). GET /admin/realms/{realm}/users/{userId}/federated-identities lists a user's links with their provenance.

What changed. A link made after the upgrade by matching a verified e-mail address never signs in an administrator. Each refusal is audited as PRIVILEGED_LINK_REFUSED. An administrator gets a trusted link in one of two ways:

  • Themselves, from the account console. Connected accounts → Link next to the provider. If they have not signed in within the step-up window (helix.account.step-up-max-age-seconds, 300 s by default), they sign in again first. Then they sign in at the provider, and the link is stored as SELF. The flow is bound to their session; an identity already linked to someone else is refused. It is audited as ACCOUNT_IDENTITY_LINK.
  • By a realm admin. For an administrator who cannot use the account console: Users → (user) → Linked identities → Confirm link, or POST /admin/realms/{realm}/users/{userId}/federated-identities/{alias}/confirm with body {"externalSubject": "…"} (one link). This needs realm-admin and is audited as FEDERATED_LINK_CONFIRMED. Like revoking trust, it also needs the user's admin permissions in every other realm they belong to.

Ordinary users are not affected: e-mail linking and just-in-time accounts work as before.

4. Actions that now need realm-admin

What changed. These used to be open to narrower permissions. See Admin roles (RBAC).

  • Signing keys and settings: every realm key write and PUT /admin/realms/{realm}/settings/signing. Reads keep manage-realm.
  • Admin grants: changing a role's admin permissions. Assigning a role, through any path, also needs the role's admin permissions to be your own (H5).
  • Acting on someone more privileged: acting on a user or client that holds admin permissions you do not hold needs those permissions, for example a password reset, impersonation or a client secret.
  • Sign-in surfaces: creating helix-console or helix-cli, and changing their Application, mappers or allowed resources. Also the realm's browser flow and the flows bound to the sign-in clients.
  • Identity providers that administrators are linked to: changing or deleting one needs the linked administrators' permissions. Changing a trusted list their wallet providers use needs the same.
  • Messaging and sign-in policy: messaging providers and templates, the MFA policy, magic links, the subject claim, and realm settings other than the display name, the legacy branding and self-registration.
  • Groups and roles: deleting a role or group, or moving a group, needs the admin permissions it grants.
  • Push devices: registering one for a user needs that user's admin permissions.
  • Unknown routes: any /admin route the permission catalogue does not name.

Also: manage-users, manage-clients, manage-identity-providers and manage-events now include their view- counterparts. A percent-encoded realm id or route name in an /admin path is refused with 400 (H4).

helix-cli is now created in every realm. On every start, a helix-cli that allows more than the built-in client is corrected: a redirect URI that is not a loopback address is dropped, as are grant types outside the built-in set, a secret, or a confidential setting. Each correction is logged and audited as SIGN_IN_CLIENT_RECONCILED. Narrower choices are kept, such as dropping device_code or a custom loopback port or path.

5. Realm signing keys, ES256 and the staging time

What changed. See Realm keys.

  • You can import a key and its certificate chain, or have the server generate a key and a CSR.
  • New keys start PENDING: published, but not signing. You activate them after helix.keys.min-staging (5 minutes by default), or earlier with ?force=true.
  • An ES256 key can be active alongside the RS256 key. Every realm keeps an active RS256 key, and retiring it is refused.
  • ID tokens use each client's id_token_signed_response_alg. Other tokens use the realm's signing.defaultAlg (RS256 by default).

What you must do. If a client asks for an ID-token algorithm that has no active key, for example RS384, change it before its next save. During a rolling upgrade you can import and stage keys, but activate an ES256 key only once every replica runs rc.12. Realm exports still contain no keys, certificates or signing settings.

6. Flyway V86

What changed. V86 (and schema.sql) changes the following:

  • realm_key: adds the certificate columns and a unique index on the public key, and rewrites the algorithm from RSA to RS256. Existing keys keep their kid and keep signing. Duplicate rows that an rc.11 race could leave are removed. If the same key is stored in two realms, the migration stops and names them.
  • New table: adds realm_signing_settings.
  • federated_link: adds realm_id and created_via, backfills both as described in section 1, and keys links by realm, provider and subject.

What you must do. Nothing; it runs on start-up.