Skip to main content

Identity providers (IdP)

An identity provider (IdP) is a service that allows users to authenticate using external accounts, such as Apple ID, Facebook, or other OIDC compatible IdP. By integrating with an identity provider, you can enable your users to sign in to your application using their existing accounts, rather than requiring them to create a new account specifically for your application.

To use an identity provider in Contember, you will need to configure the identity provider in the system and then provide a way for users to initiate the authentication process. This can typically be done by providing a login button or link that redirects the user to the identity provider's authentication page.

Once the user has authenticated with the identity provider, they will be redirected back to your application, where Contember will handle the rest of the authentication process. If the user's identity can be successfully verified, they will be logged in to your application.

IdP configuration

Adding new IdP

To add a new identity provider (IdP) in Contember, you will need to use the addIDP mutation provided by the tenant API. This mutation allows you to specify the details of the identity provider you want to add, including its type, configuration, and options.

Example how to use the addIDP mutation to add a new OIDC identity provider:

mutation {
addIDP(
identityProvider: "oidc-provider",
type: "oidc",
configuration: {
url: "https://oidc-provider.com/.well-known/openid-configuration",
clientId: "YOUR_CLIENT_ID",
clientSecret: "YOUR_CLIENT_SECRET",
responseType: "code",
claims: "openid email"
},
options: {
autoSignUp: true,
exclusive: false
}
) {
ok
error {
code
developerMessage
}
}
}
claims vs scope

Note that claims in configuration are actually "scopes" in OIDC terminology. This will be fixed in a future version.

In this example, the identityProvider field is set to "oidc-provider", which is a custom slug that you can use to identify the identity provider in your application. The type field is set to "oidc" to indicate that this is an OIDC identity provider.

The configuration field should include the URL of the provider's OpenID Connect configuration, as well as the client ID and client secret provided by the provider. The responseType and claims fields are optional.

The options field allows you to specify additional options for the identity provider, such as whether to automatically sign up users who don't already have an account and whether to allow only this identity provider for authentication.

If the "ok" in response is false, you will find details in error, possible error codes are following: ALREADY_EXISTS, UNKNOWN_TYPE, INVALID_CONFIGURATION

Updating existing IdP

To update an existing identity provider (IdP) in Contember, you will need to use the updateIDP mutation. This mutation allows you to specify the updated details of the identity provider you want to update, including its configuration and options.

Example how to use the updateIDP mutation to update an existing OIDC identity provider:

mutation {
updateIDP(
identityProvider: "oidc-provider",
configuration: {
url: "https://new-oidc-provider.com/.well-known/openid-configuration",
clientId: "NEW_CLIENT_ID",
clientSecret: "NEW_CLIENT_SECRET",
responseType: "code",
claims: "openid email profile"
},
options: {
autoSignUp: false,
exclusive: false
}
) {
ok
error {
code
developerMessage
}
}
}

In this example, the identityProvider field is set to "oidc-provider", which is the custom slug that you used to identify the identity provider when you added it to Contember.

The configuration field should include the updated details for the identity provider, such as the URL of the provider's OpenID Connect configuration, the client ID and client secret provided by the provider, and any optional parameters such as responseType and claims.

The options field allows you to specify updated options for the identity provider, such as whether to automatically sign up users who don't already have an account and whether to allow only this identity provider for authentication.

If the "ok" in response is false, you will find details in error, possible error codes are following: NOT_FOUND, INVALID_CONFIGURATION

Temporarily disabling and enabling an IdP

In Contember, you can enable or disable an identity provider (IdP) using the enableIDP and disableIDP mutations. These mutations allow you to control whether an identity provider is available.

To disable an identity provider, you can use the disableIDP mutation like this:

mutation {
disableIDP(identityProvider: "oidc-provider") {
ok
error {
code
developerMessage
}
}
}

In this example, the identityProvider field is set to "oidc-provider", which is the custom slug that you used to identify the identity provider when you added it to Contember.

When you execute the disableIDP mutation, it will return a response indicating whether the operation was successful. If the operation was not successful, the ok field will be set to false and the error field will contain details about the error that occurred. Possible error code is NOT_FOUND.

To enable a previously disabled identity provider, you can use the enableIDP mutation like this:

mutation {
enableIDP(identityProvider: "oidc-provider") {
ok
error {
code
developerMessage
}
}
}

The enableIDP mutation works in a similar way to the disableIDP mutation, with the identityProvider field specifying the custom slug of the identity provider you want to enable.

When you execute the disableIDP mutation, it will return a response indicating whether the operation was successful. If the operation was not successful, the ok field will be set to false and the error field will contain details about the error that occurred. Possible error code is NOT_FOUND.

IdP authentication

A two-step exchange: initSignInIDP produces the redirect URL and any state your client must remember, the user authenticates at the provider, and signInIDP consumes the callback URL to mint a session.

Both mutations carry their provider-specific arguments inside a data: Json field. Older redirectUrl, idpResponse, and sessionData top-level arguments still work but are deprecated and should not be used in new integrations.

Step 1 — initiate

mutation {
initSignInIDP(
identityProvider: "oidc-provider",
data: { redirectUrl: "https://my-app.dev/finish-auth" }
) {
ok
error { code developerMessage }
result {
authUrl
sessionData
idpConfiguration
}
}
}

The identityProvider field is the slug used when the IdP was added. data.redirectUrl is where the provider should send the user after authentication. The exact data shape is provider-specific — for OIDC the supported key is redirectUrl.

The response carries:

  • authUrl — redirect the browser here.
  • sessionData — opaque blob you must keep alongside the browser session (carries state, nonce, code verifier, …). Pass it back into signInIDP verbatim.
  • idpConfiguration — only set when the IDP was created with initReturnsConfig: true; useful for clients that need to drive the auth flow themselves.

Error codes: PROVIDER_NOT_FOUND, IDP_VALIDATION_FAILED.

Step 2 — complete

Once the IDP redirects back to your redirectUrl, take the full callback URL (with ?code=…&state=…) and submit it together with the sessionData from step 1:

mutation {
signInIDP(
identityProvider: "oidc-provider",
data: {
url: "https://my-app.dev/finish-auth?code=ABC123&state=XYZ789",
sessionData: { nonce: "123456", state: "XYZ789" },
redirectUrl: "https://my-app.dev/finish-auth"
},
expiration: 60,
options: { trustForwardedClientInfo: true } # optional, see proxy-trust.md
) {
ok
error { code developerMessage }
result {
token
person { id email }
idpResponse
}
}
}

data.url is the full callback URL the IDP sent the user to. data.sessionData is the blob returned by initSignInIDP. data.redirectUrl must match what was passed to initSignInIDP.

The response result.token is the session API key — store it client-side and use it as the Bearer token for subsequent requests. idpResponse exposes the provider's raw token-exchange response when you need access tokens / userinfo claims.

{
"ok": true,
"error": null,
"result": {
"token": "XXX",
"person": { "id": "user-uuid", "email": "[email protected]" }
}
}

Error codes: INVALID_IDP_RESPONSE, IDP_VALIDATION_FAILED, PERSON_NOT_FOUND, PERSON_DISABLED, PERSON_ALREADY_EXISTS.

Audit

Available since 2.2

Every IdP management call is recorded in the audit log:

MutationAudit typeevent_data
addIDPidp_create{identityProvider, type, configurationKeys, options} — only the names of the configuration keys, never the secret values
updateIDPidp_update{before, after} with configuration collapsed the same way
disableIDPidp_disable{identityProvider}
enableIDPidp_enable{identityProvider}

Sign-in attempts via IdP are recorded as idp_login.