انتقل إلى المحتوى الرئيسي

Class: KeycloakIdentityProvider

Defined in: packages/identity/src/keycloak.ts:92

The IdentityProvider for Keycloak, over its admin REST API.

It authenticates as the master realm's administrator through the provider's own admin-cli client and holds the token only for its short life. Realm names are Keycloak realm names. The managed marker is the client attribute oktoid.managed=true; a client of slice 0 with the engine's old description is adopted and marked.

Behaviour is copied from slice 0's packages/bootstrap/src/idp/keycloak.ts and converge.ts and extended; those files are removed by step 1.8a.

What differs from WSO2, so a caller is not surprised: the SMTP password and a client's secret are write-only (Keycloak masks them), so a rotated SMTP password is written only when another SMTP field changes; the oktoid-api style scope is kept out of the scope claim; the refresh and ID token lifetimes are tied to the SSO idle and access token lifetimes.

Implements​

Constructors​

Constructor​

new KeycloakIdentityProvider(options): KeycloakIdentityProvider

Defined in: packages/identity/src/keycloak.ts:96

Parameters​

options​

KeycloakProviderOptions

Returns​

KeycloakIdentityProvider

Properties​

kind​

readonly kind: "keycloak" = 'keycloak'

Defined in: packages/identity/src/keycloak.ts:93

Which vendor this is.

Implementation of​

IdentityProvider.kind

Methods​

assertNoDirectGrants()​

assertNoDirectGrants(realm): Promise<Ensured<{ checked: number; }>>

Defined in: packages/identity/src/keycloak.ts:193

Turns the direct access grant off on every client of the realm that has it on, ours and the provider's built-ins, then reads the realm again and refuses to return while any client still allows it. Run on every converge.

Parameters​

realm​

string

Returns​

Promise<Ensured<{ checked: number; }>>

changed when it had to switch any off; the value counts clients checked.

Throws​

direct_grants_remain, naming the clients.

Implementation of​

IdentityProvider.assertNoDirectGrants


disableClient()​

disableClient(realm, clientId, options?): Promise<Ensured<ClientView>>

Defined in: packages/identity/src/keycloak.ts:131

Disables a client so it can obtain no tokens. Does not delete it and does not revoke tokens already issued, which expire with their own lifetime. Idempotent: a disabled client gives changed: false.

By default only a managed client (PO-QA1: one the answer file no longer declares). With options.undeclared, also one without the marker (PO-QA2: a client nobody declared, in a realm the platform owns). Never a provider's built-in client (BUILT_IN_CLIENTS), whatever the options say.

Disabling is what keeps a client off. A disabled client that is then deleted at the provider is created again, enabled, by IdentityProvider.ensureClient on the next run if the answer file still declares it.

Parameters​

realm​

string

clientId​

string

options?​

DisableClientOptions = {}

Returns​

Promise<Ensured<ClientView>>

Throws​

not_managed for a built-in client, and for a client without the marker unless options.undeclared; not_found when there is none.

Implementation of​

IdentityProvider.disableClient


ensureAudienceMapper()​

ensureAudienceMapper(realm, spec): Promise<Ensured<MapperView>>

Defined in: packages/identity/src/keycloak.ts:143

Makes tokens obtained with spec.scope carry spec.audience. On Keycloak that is a mapper on the client scope; on WSO2 it is a registry the adapter keeps and applies to each client when the client is ensured.

Parameters​

realm​

string

spec​

AudienceMapperSpec

Returns​

Promise<Ensured<MapperView>>

Throws​

not_found when the scope does not exist.

Implementation of​

IdentityProvider.ensureAudienceMapper


ensureClient()​

ensureClient(realm, spec): Promise<Ensured<ClientView>>

Defined in: packages/identity/src/keycloak.ts:123

Creates or converges one client and marks it managed. Direct access grants are always off. See ClientSpec for what each kind must be.

A client that exists and is disabled stays disabled (value.enabled is false): the call converges everything else about it and never enables it. A machine client's secret is then neither tested nor set, because a disabled client obtains no token to test it with; on WSO2 that also means a disabled application is never deleted and created again for a new secret. The caller reports the client; the secret converges on the first run after an administrator enables it.

A client that does not exist is created, enabled. That includes one the engine or an administrator disabled and somebody then deleted at the provider: if the answer file still declares it, the next run brings it back, enabled.

Parameters​

realm​

string

spec​

ClientSpec

Returns​

Promise<Ensured<ClientView>>

Throws​

conflict when a client of that id exists and is not managed; not_found when a named scope does not exist.

Implementation of​

IdentityProvider.ensureClient


ensureRealm()​

ensureRealm(realm, spec): Promise<Ensured<RealmView>>

Defined in: packages/identity/src/keycloak.ts:119

Creates the realm if absent, then converges the settings in spec.

Parameters​

realm​

string

The logical realm name.

spec​

RealmSpec

What it should be. Absent fields are left alone.

Returns​

Promise<Ensured<RealmView>>

Throws​

forbidden when the credential may not create realms.

Implementation of​

IdentityProvider.ensureRealm


ensureScope()​

ensureScope(realm, spec): Promise<Ensured<ScopeView>>

Defined in: packages/identity/src/keycloak.ts:139

Creates or converges a scope.

Parameters​

realm​

string

spec​

ScopeSpec

Returns​

Promise<Ensured<ScopeView>>

Implementation of​

IdentityProvider.ensureScope


ensureSessionSettings()​

ensureSessionSettings(realm, settings): Promise<Ensured<SessionView>>

Defined in: packages/identity/src/keycloak.ts:186

Converges the session and token settings in settings (absent fields are left alone). Settings the provider keeps per client are applied to every managed client. Fields it cannot set are in unsupported.

Parameters​

realm​

string

settings​

Partial<SessionSettings>

Returns​

Promise<Ensured<SessionView>>

Implementation of​

IdentityProvider.ensureSessionSettings


ensureUser()​

ensureUser(realm, spec): Promise<EnsuredUser>

Defined in: packages/identity/src/keycloak.ts:154

Creates a user if absent and returns its provider subject. A user that exists is not modified (the person may already have completed the actions) and no mail is sent. For a new user with invite, sends the required-action mail through the realm's SMTP; a mail failure is reported in invitationFailure and does not undo the user.

Parameters​

realm​

string

spec​

UserSpec

Returns​

Promise<EnsuredUser>

Implementation of​

IdentityProvider.ensureUser


listClients()​

listClients(realm): Promise<readonly ClientView[]>

Defined in: packages/identity/src/keycloak.ts:127

Every client of the realm, ours and the provider's own, with managed set.

Parameters​

realm​

string

Returns​

Promise<readonly ClientView[]>

Implementation of​

IdentityProvider.listClients


listMappers()​

listMappers(realm, scope?): Promise<readonly MapperView[]>

Defined in: packages/identity/src/keycloak.ts:150

The audience mappers of the realm, optionally of one scope.

Parameters​

realm​

string

scope?​

string

Returns​

Promise<readonly MapperView[]>

Implementation of​

IdentityProvider.listMappers


probe()​

probe(realm?): Promise<ProbeResult>

Defined in: packages/identity/src/keycloak.ts:111

Reads the server's version and tries each management capability: first a read, then a create-and-delete of an object named oktoid-probe-<uuid>. Whatever it creates it deletes, including on failure. It never writes outside the probe's own objects.

Parameters​

realm?​

string

The realm to probe the realm-scoped capabilities in. When it does not exist those capabilities are indeterminate; probe again after ensureRealm.

Returns​

Promise<ProbeResult>

Every capability, once. Use probeOutcome for D1.14's three outcomes.

Throws​

credential_refused when the credential is not accepted at all; every other failure becomes a capability state.

Implementation of​

IdentityProvider.probe


readInvitationAcceptance()​

readInvitationAcceptance(realm, subject): Promise<InvitationAcceptance>

Defined in: packages/identity/src/keycloak.ts:167

Reads whether an invited user has taken up their account. A read: it changes nothing and sends no mail. It exists for the setup wizard's last step, which waits for the root account's holder and has no other way to see them arrive.

What each adapter reads:

  • Keycloak: the user's outstanding required actions and whether a password credential exists. Keycloak clears an action when the person completes it, so none outstanding and a password present is accepted; anything else is pending. It never answers unknown.
  • WSO2: the account state WSO2 keeps for its ask-password and forced-reset flows. A PENDING_* state is pending and UNLOCKED is accepted. It says the password was set and nothing about the second factor, which a WSO2 user enrols at their first sign-in with no per-user record the management API returns. A user without the claim, or locked or disabled, is unknown.

A user who existed before the engine ran and was never invited reads accepted on both, which is true of the account and says nothing of an invitation.

Parameters​

realm​

string

subject​

string

The provider subject from IdentityProvider.ensureUser.

Returns​

Promise<InvitationAcceptance>

Throws​

not_found when the realm or the user does not exist; unreachable when the provider could not be asked, which a caller reports as not checked.

Implementation of​

IdentityProvider.readInvitationAcceptance


readRealm()​

readRealm(realm, options?): Promise<RealmView | undefined>

Defined in: packages/identity/src/keycloak.ts:115

Reads a realm: its issuer and keys (from its own discovery document, never composed from configuration) and the settings this port knows.

Parameters​

realm​

string

The logical realm name.

options?​

ReadRealmOptions

What to read beyond the realm's settings; see ReadRealmOptions.

Returns​

Promise<RealmView | undefined>

The realm, or undefined when it does not exist.

Implementation of​

IdentityProvider.readRealm


readSessionSettings()​

readSessionSettings(realm): Promise<SessionView>

Defined in: packages/identity/src/keycloak.ts:182

Reads the session and token settings, for the bring-your-own report, without writing.

Parameters​

realm​

string

Returns​

Promise<SessionView>

Implementation of​

IdentityProvider.readSessionSettings


resendInvitation()​

resendInvitation(realm, subject, actions, options?): Promise<void>

Defined in: packages/identity/src/keycloak.ts:158

Sends the required-action mail again, to a user the engine created.

Parameters​

realm​

string

subject​

string

The provider subject from IdentityProvider.ensureUser.

actions​

readonly ("verify-email" | "update-password" | "configure-totp")[]

options?​

InvitationOptions

The link's lifetime; see InvitationOptions.

Returns​

Promise<void>

Throws​

rejected when the realm has no working SMTP.

Implementation of​

IdentityProvider.resendInvitation


resolveMachineIdentity()​

resolveMachineIdentity(realm, clientId, secret): Promise<MachineIdentity | undefined>

Defined in: packages/identity/src/keycloak.ts:174

Proves a machine client's secret is the one the engine holds, by using it, and returns what its tokens say. The secret is sent and never read back.

Parameters​

realm​

string

clientId​

string

secret​

Secret<string>

Returns​

Promise<MachineIdentity | undefined>

The identity, or undefined when the provider refuses the secret.

Implementation of​

IdentityProvider.resolveMachineIdentity