Working with Identity Providers
Configuring SAML JIT Provisioning
SAML Just-In-Time (JIT) Provisioning automates user account creation when the user first tries to perform SSO and the user doesn't yet exist in Oracle Identity Cloud Service. In addition to automatic user creation, SAML JIT Provisioning allows granting and revoking group memberships as part of provisioning. SAML JIT Provisioning can be configured to update provisioned users so the users' attributes in the Service Provider (SP) store can be kept in sync with the Identity Provider (IDP) user store attributes.
Note:
SAML JIT Provisioning is disabled by default and must be enabled by Oracle. To enable SAML JIT Provisioning, file a Service Request with My Oracle Support.When configuring SAML JIT Provisioning, you define how the user data sent by your SAML IDP will be used to create and/or update users in your Identity Cloud Service stripe. First, you create and configure a SAML IDP for federated SSO, and then you enable and configure the SAML JIT Provisioning options for that IDP.
SAML JIT Provisioning can be configured only via the /admin/v1/IdentityProviders
REST API endpoint.
IdentityProvider Property |
Description | JSON Example |
---|---|---|
jitUserProvEnabled |
Boolean property to enable/disable the SAML JIT Provisioning feature for this IDP. If this property istrue at least one of jitUserProvCreateUserEnabled or jitUserProvAttributeUpdateEnabled also must be true . |
|
jitUserProvCreateUserEnabled |
Boolean property indicating whether a user should be created, based on the incoming assertion, if the user does not yet exist. By default, users created using SAML JIT Provisioning are "federated" users. Federated users don't have credentials to sign in directly to Oracle Identity Cloud Service, but instead must be authenticated by the external identity provider. A user's federated status can be changed using the Admin console, as well as by updating the |
|
jitUserProvAttributeUpdateEnabled |
Boolean property indicating whether the user's attributes should be updated, based on the incoming assertion, if the user already exists. |
|
jitUserProvAttributes |
This is a reference to a See below for details of the |
|
jitUserProvGroupAssertionAttributeEnabled |
Boolean property indicating whether group memberships should be assigned to the user based on a list of group names received from the IDP in a SAML attribute. If this property is |
|
jitUserProvGroupMappingMode |
String property that controls how the groups in IdP are mapped to those in Identity Cloud Service tenant. The value must be one of: explicit - IdP groups are explicitly mapped to the groups in Identity Cloud Service tenant via the configuration property implicit - Group names in the SAML assertion must match group names in the Identity Cloud Service tenant. Defaults to explicit if no value is specified. |
|
jitUserProvGroupMappings |
Array of mappings between groups in the IdP assertion and groups in the Identity Cloud Service tenant. Every object in the array represents a mapping between an IdP group and an Identity Cloud Service group.
The maximum number of group mappings per IdP is 250. |
|
jitUserProvGroupSAMLAttributeName |
The name of the SAML assertion attribute that will contain groups to be assigned to the user, if the property
The assertion attribute can comprise either:
|
|
jitUserProvGroupStaticListEnabled |
Boolean property indicating whether group memberships should be assigned to the user based on a static list of group names. If this property is |
|
jitUserProvAssignedGroups |
Array of groups to be assigned to the user, in addition to any values received in the SAML assertion, if the property Note: The values set in this array are group IDs (not group names). |
|
jitUserProvGroupAssignmentMethod |
String property that controls how group memberships will be assigned to the Identity Cloud Service user. The value must be one of:
|
|
jitUserProvIgnoreErrorOnAbsentGroups |
Boolean property that determines the action to take when the incoming assertion attribute specifies a group that does not exist or a group for which a group mapping does not exist in the Identity Cloud Service tenant. If this property is true, then the missing group is ignored, and the user is created. If this property is false, and a nonexistent group is specified, user creation will fail. Defaults to true for explicit mode, and false for implicit mode specified via |
|
Configuring the jitUserProvAttributes
Mapping
Once the IdentityProvider
has been created, and the SAML JIT Provisioning attributes configured as needed, the jitUserProvAttributes
resource must be updated to add your inbound attribute mappings. The MappedAttributes
resource, referenced by jitUserProvAttributes
, is automatically created and deleted with the IdentityProvider
resource, and this property is marked immutable. The SAML JIT Provisioning attribute mappings are configured by updating the existing MappedAttributes
object, not by replacing it.
MappedAttributes
properties used by SAML JIT Provisioning.
MappedAttributes Property |
Description | JSON Examples |
---|---|---|
attributeMappings |
The list of mappings between the SAML assertion attributes and the Identity Cloud Service user attributes. Each mapping consists of:
Note: SAML assertion attribute names are case-sensitive. |
|
refResourceType |
The name of the resource that is using/has a reference to this mapped attribute (always |
|
idcsResourceType |
The type of the Identity Cloud Service resource to which we are mapping (always |
|
direction |
Direction of the mapping, with respect to the Identity Cloud Service resource in question (always |
|
refResourceID |
The ID of the |
|
To update the attribute mappings, first you must identify the correct MappedAttributes
resource for your IDP. This can be done by retrieving the IdentityProvider
resource, and looking at the $ref
attribute of the jitUserProvAttributes
property.
For example, you might have a MappedAttributes
resource such as https://tenant-base-url/admin/v1/MappedAttributes/6533d475754845a8b0e971c48b87edda
, which you would then PATCH to update its attributeMappings
property.
Sample PATCH payload for MappedAttributes
{
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:PatchOp"
], "Operations": [
{
"op": "replace",
"path": "attributeMappings",
"value": [
{
"managedObjectAttributeName": "$(assertion.mail)",
"idcsAttributeName": "userName"
},
{
"managedObjectAttributeName": "$(assertion.firstname)",
"idcsAttributeName": "name.givenName"
},
{
"managedObjectAttributeName": "$(assertion.lastname)",
"idcsAttributeName": "name.familyName"
},
{
"managedObjectAttributeName": "$(assertion.mail)",
"idcsAttributeName": "emails[primary eq true and type eq \"work\"].value"
}
]
}
]
}
SAML JIT Provisioning Attribute Mapping Usage and Runtime Behavior
If values for userName
, name.givenName
and name.familyName
are not present, there is an error at runtime, since those attributes are marked required in the User
schema. The same is true for primary email address, unless the tenant has been configured to make that optional.
At runtime, if any assertion attribute value cannot be converted to a data type that can be assigned to the user attribute to which its mapped, there will be an error and SSO will fail.
If multiple attribute mappings are configured targeting the same Identity Cloud Service user attribute, they are evaluated and executed in position order, and only the last mapping's result is retained.
An incoming assertion attribute that contains no values will result in the removal of the value from the corresponding mapped Identity Cloud Service user attribute, if jitUserProvAttributeUpdateEnabled
is true
.
${assertion.fed.issuerid)
$(assertion.fed.nameidvalue)
- Sensitive attributes - i.e., attributes marked
"idcsSensitive: hash"
or"idcsSensitive: encrypt"
in the schema - Attributes that are marked
"idcsInternal: true"
in the schema - Attributes that are readOnly
- All attributes that User Sync disallows
When a user is created via SAML JIT Provisioning, the following attributes will be set. These attributes aren't configurable:
bypassNotification : true
- For example, an account activation email will not be sent to the newly-created user.syncedFromApp
- A reference to the Identity Provider resource corresponding to the issuer of the inbound SAML assertion.
isFederatedUser
attribute is set to
true
by default. This behavior can be changed by setting the
isFederatedUser
attribute to
false
in the SAML JIT Provisioning
attributeMappings
configuration.
Note:
This default behavior (isFederatedUser = true
) applies only to user creation, not user update; the
attributeMappings
configuration applies to both user creation and user update.
Frequently Asked Questions
Q: Is it mandatory for groups to be present in Identity Cloud Service to update group membership during SAML JIT Provisioning?
A: Yes. Groups needs to be synced or created manually in Identity Cloud Service before group membership is updated. SAML JIT Provisioning will not create groups on the fly.
Q: Can I map a literal in attribute mapping? For example, I want to map isFederatedUser = true
during user creation?
A: Yes.
Q: Do we support multi-value attributes in attribute mapping? If yes, do we patch the payload or do an override?
A: Yes. All values of the Identity Cloud Service user attribute are replaced with the net result of the SAML JIT Provisioning attribute mapping.
Q: If a user is removed from a group in the IDP, how do we handle it? What if that group is manually assigned in Identity Cloud Service? Can we configure replace versus patch behavior?
A: Group assignment via SAML JIT Provisioning update can be configured to have either Merge or Overwrite behavior, for the user's group assignments overall. For example, if update is configured for Overwrite, any manual group assignments that do not appear in the IDP assertion, will be removed.
Q: Can we configure SAML JIT Provisioning to occur only during user creation, but not to update the user later?
A: Yes. If jitUserProvCreateUserEnabled
is true and jitUserProvAttributeUpdateEnabled
is false, SAML JIT Provisioning will create users if they are missing, but will not update them on subsequent logins.
Custom Social Identity Providers
This use case discusses how to get Oracle Identity Cloud Service to authenticate using a custom Social Identity Provider (IdP) type.
You can set up the metadata for a custom social identity provider using the examples below.
/admin/v1/SocialIdentityProviderMetadata
.
- to add a global level provider, invoke the
<tenant-base-url>/admin/v1/SocialIdentityProviderMetadata
endpoint. - To add a tenant level provider, invoke the
<idcs-oracle-url>/admin/v1/SocialIdentityProviderMetadata
endpoint.
Note:
If custom social identity providers with same name have been defined usingSocialIdentityProviderMetadata
at both global and tenant level, the custom social identity provider defined at the tenant level takes precedence.
- By choosing it from the console. Choose Security, then Identity Providers, then Add Social IDP and choose the new identity provider.
- From the
/admin/v1/SocialIdentityProviders
REST API.
The new custom social identity provider is available as one of the Social Identity Provider Types.
Login Use Cases
These login use cases show how to change the AuthorizePhase
, loginScopes
, tokenPhase
, and userInfoPhase
depending on the provider.
In these samples, Expressions( starting with $) refer to the parameter values that are not constant:
$socialIdentityProvider
represents the correspondingSocialIdentityProvider
resource. For example,$socialIdentityProvider.consumerKey
refers to the client secret configured in the tenant specific social identity provider profile.${state}
is the state generated by the Identity Cloud Service runtime while sending the Authorize request to the social idp.${redirectUri}
is the tenant specific callback URL generated by the Identity Cloud Service runtime.${scope}
refers to:- In login use-case, the scope string specified as value of the
loginScopes
attribute. -
In provisioning use-case, the scope string specified as value of the
provisioningScopes
attribute.
- In login use-case, the scope string specified as value of the
${clientCredentials}
is the standard base-64 encoded representation of client id and client secret as required in the authorization header for Basic authentication scheme.${authorizationCode}
refers to the authorization code received with callback from the social idp.
In the following sections, there is sample metadata for the login use case, followed by two examples. Then the sample metadata for the provisioning use case.
Sample Metadata for Login use case
{
"type": "SampleProviderForLogin",
"status": "enabled",
"idAttribute": "email",
"capabilities": [
"login"
],
"authorizePhase": {
"loginScopes": "<scope string>",
"url": "<Authorization endpoint>"
},
"authorizePhaseParameters": [
{
"value": "${socialIdentityProvider.consumerKey}",
"name": "client_id"
},
{
"value": "code",
"name": "response_type"
},
{
"value": "${scope}",
"name": "scope"
},
{
"value": "${state}",
"name": "state"
},
{
"value": "${redirectUri}",
"name": "redirect_uri"
}
],
"tokenPhase": {
"url": "<Token endpoint>",
"method": "<HTTP method for Token endpoint - get/post>"
},
"tokenPhaseHeaders": [
{
"value": "application/json",
"name": "Accept"
},
{
"value": "Basic ${clientCredentials}",
"name": "Authorization"
}
],
"tokenPhaseParameters": [
{
"value": "${socialIdentityProvider.consumerKey}",
"name": "client_id"
},
{
"value": "${socialIdentityProvider.consumerSecret}",
"name": "client_secret"
},
{
"value": "${redirectUri}",
"name": "redirect_uri"
},
{
"value": "${authorizationCode}",
"name": "code"
},
{
"value": "authorization_code",
"name": "grant_type"
}
],
"userInfoPhase": {
"url": "<UserInfo endpoint>",
"method": "<HTTP method for UserInfo endpoint - get/post>"
},
"userInfoPhaseHeaders": [
{
"value": "*/*",
"name": "Accept"
},
{
"value": "token ${accessToken}",
"name": "Authorization"
}
],
"userInfoPhaseParameters": [
{
"name": "access_token",
"value": "${accessToken}"
}
],
"userInfoAttributeMappings": [
{
"idpAttribute": "firstname",
"idcsAttribute": "given_name"
},
{
"idpAttribute": "lastname",
"idcsAttribute": "family_name"
},
{
"idpAttribute": "email.primary",
"idcsAttribute": "email"
}
],
"iconUrl": "<icon url>",
"schemas": [
"urn:ietf:params:scim:schemas:oracle:idcs:SocialIdentityProviderMetadata"
]
}
Example: GitHub
{
"type": "GitHub",
"status": "enabled",
"idAttribute": "email",
"capabilities": [
"login"
],
"authorizePhase": {
"loginScopes": "user user:email",
"url": "http://github.com/login/oauth/authorize"
},
"authorizePhaseParameters": [
{
"value": "${socialIdentityProvider.consumerKey}",
"name": "client_id"
},
{
"value": "code",
"name": "response_type"
},
{
"value": "${scope}",
"name": "scope"
},
{
"value": "${state}",
"name": "state"
},
{
"value": "${redirectUri}",
"name": "redirect_uri"
}
],
"tokenPhase": {
"url": "https://github.com/login/oauth/access_token",
"method": "post"
},
"tokenPhaseHeaders": [
{
"value": "application/json",
"name": "Accept"
},
{
"value": "Basic ${clientCredentials}",
"name": "Authorization"
}
],
"tokenPhaseParameters": [
{
"value": "${socialIdentityProvider.consumerKey}",
"name": "client_id"
},
{
"value": "${socialIdentityProvider.consumerSecret}",
"name": "client_secret"
},
{
"value": "${redirectUri}",
"name": "redirect_uri"
},
{
"value": "${authorizationCode}",
"name": "code"
},
{
"value": "authorization_code",
"name": "grant_type"
}
],
"userInfoPhase": {
"url": "https://api.github.com/user",
"method": "get"
},
"userInfoPhaseHeaders": [
{
"value": "*/*",
"name": "Accept"
},
{
"value": "token ${accessToken}",
"name": "Authorization"
}
],
"userInfoPhaseParameters": [
{
"name": "access_token",
"value": "${accessToken}"
}
],
"userInfoAttributeMappings": [
{
"idpAttribute": "name",
"idcsAttribute": "given_name"
}
],
"iconUrl": "<<iconURL>>",
"schemas": [
"urn:ietf:params:scim:schemas:oracle:idcs:SocialIdentityProviderMetadata"
]
}
IDCS as IdentityProvider (with username mapping)
Set email as optional in IDCS using a patch operation in https://{{host}}/admin/v1/IdentitySettings/IdentitySettings
.
{
{
"schemas":
[
"urn:ietf:params:scim:api:messages:2.0:PatchOp"
],
"Operations":
[
{
"op": "replace",
"path": "primaryEmailRequired",
"value": false
}
]
}
}
Example:
{
"type": "IDCSProvider",
"status": "enabled",
"idAttribute": "preferred_username",
"capabilities": [
"login"
],
"authorizePhase": {
"loginScopes": "openid profile email",
"url": "https://idcs-idp-where-login-happen.identity.oraclecloud.com/oauth2/v1/authorize"
},
"authorizePhaseParameters": [
{
"value": "${socialIdentityProvider.consumerKey}",
"name": "client_id"
},
{
"value": "code",
"name": "response_type"
},
{
"value": "${scope}",
"name": "scope"
},
{
"value": "${state}",
"name": "state"
},
{
"value": "${redirectUri}",
"name": "redirect_uri"
}
],
"tokenPhase": {
"url": "https://idcs-idp-where-login-happen.identity.oraclecloud.com/oauth2/v1/token",
"method": "post"
},
"tokenPhaseHeaders": [
{
"value": "application/x-www-form-urlencoded",
"name": "Content-Type"
},
{
"value": "Basic ${clientCredentials}",
"name": "Authorization"
}
],
"tokenPhaseParameters": [
{
"value": "${authorizationCode}",
"name": "code"
},
{
"value": "authorization_code",
"name": "grant_type"
}
],
"userInfoPhase": {
"url": "https://idcs-idp-where-login-happen.identity.oraclecloud.com/oauth2/v1/userinfo",
"method": "get"
},
"userInfoPhaseHeaders": [
{
"value": "application/x-www-form-urlencoded",
"name": "Content-Type"
},
{
"value": "Bearer ${accessToken}",
"name": "Authorization"
}
],
"userInfoPhaseParameters": [
{
"name": "access_token",
"value": "${accessToken}"
}
],
"schemas": [
"urn:ietf:params:scim:schemas:oracle:idcs:SocialIdentityProviderMetadata"
]
}
Example: Okta
{
"type": "OktaTest",
"status": "enabled",
"idAttribute": "email",
"capabilities": [
"login"
],
"authorizePhase": {
"loginScopes": "openid profile email",
"url": "<Okta's UserInfo endpoint>"
},
"authorizePhaseParameters": [
{
"name": "client_id",
"value": "${socialIdentityProvider.consumerKey}"
},
{
"name": "response_type",
"value": "code"
},
{
"name": "scope",
"value": "${scope}"
},
{
"name": "state",
"value": "${state}"
},
{
"name": "redirect_uri",
"value": "${redirectUri}"
}
],
"tokenPhase": {
"url": "<Okta's UserInfo endpoint>",
"method": "post"
},
"tokenPhaseHeaders": [
{
"value": "application/json",
"name": "Accept"
}
],
"tokenPhaseParameters": [
{
"value": "${socialIdentityProvider.consumerKey}",
"name": "client_id"
},
{
"value": "${socialIdentityProvider.consumerSecret}",
"name": "client_secret"
},
{
"value": "${redirectUri}",
"name": "redirect_uri"
},
{
"value": "${authorizationCode}",
"name": "code"
},
{
"value": "authorization_code",
"name": "grant_type"
}
],
"userInfoPhase": {
"url": "<Okta's UserInfo endpoint>",
"method": "post"
},
"userInfoPhaseHeaders": [
{
"value": "*/*",
"name": "Accept"
},
{
"value": "Bearer ${accessToken}",
"name": "Authorization"
}
],
"iconUrl": "<<iconURL>>",
"schemas": [
"urn:ietf:params:scim:schemas:oracle:idcs:SocialIdentityProviderMetadata"
]
}
Sample Metadata for Provisioning use case
{
"type": "SampleProviderForProvisioning",
"status": "enabled",
"capabilities": [
"provisioning"
],
"authorizePhase": {
"provisioningScopes": "<scope string>",
"url": "<Authorization endpoint>"
},
"authorizePhaseParameters": [
{
"value": "${socialIdentityProvider.consumerKey}",
"name": "client_id"
},
{
"value": "code",
"name": "response_type"
},
{
"value": "${scope}",
"name": "scope"
},
{
"value": "${state}",
"name": "state"
},
{
"value": "${redirectUri}",
"name": "redirect_uri"
}
],
"tokenPhase": {
"url": "<Token endpoint>",
"method": "<HTTP method for Token endpoint - get/post>"
},
"tokenPhaseHeaders": [
{
"value": "application/json",
"name": "Accept"
},
{
"value": "Basic ${clientCredentials}",
"name": "Authorization"
}
],
"tokenPhaseParameters": [
{
"value": "${socialIdentityProvider.consumerKey}",
"name": "client_id"
},
{
"value": "${socialIdentityProvider.consumerSecret}",
"name": "client_secret"
},
{
"value": "${redirectUri}",
"name": "redirect_uri"
},
{
"value": "${authorizationCode}",
"name": "code"
},
{
"value": "authorization_code",
"name": "grant_type"
}
],
"refreshTokenPhaseHeaders": [
{
"value": "application/json",
"name": "Accept"
}
],
"refreshTokenPhaseParameters": [
{
"value": "${socialIdentityProvider.consumerKey}",
"name": "client_id"
},
{
"value": "${socialIdentityProvider.consumerSecret}",
"name": "client_secret"
},
{
"value": "${refreshToken}",
"name": "refresh_token"
}