JIT provisioning & user association with WSO2IS

Federated users can be provisioned to WSO2IS local user store using JIT provisioning. But; WSO2IS can not enforce end users to enter new attributes for provisioning.

But; WSO2IS 5.3.0 contains new feature which end user’s can fill out the mandatory attributes for given service provider. Assume that federated IDP or local IDP does not contain the required end user’s attributes which SP is looking for; then end user can provide them as user inputs. You can find more details from this mail thread.
These provided attributes will be sent to the SP, But; they will not be provisioned by default with federated JIT provisioning. Lets see how we can provision them. This can be done via implementing an extension to WSO2IS.
Step 1. Extend the DefaultStepBasedSequenceHandler & implement a new sequence handler. Here; we need to extend only the “handleJitProvisioning()” method. Sample code can be found as following

    protected void handleJitProvisioning(String subjectIdentifier, AuthenticationContext context, List<String> mappedRoles, Map<String, String> extAttributesValueMap)
            throws FrameworkException {
        
        subjectIdentifier = new StringBuilder().append(subjectIdentifier).append("@").append(context.getTenantDomain()).toString();
        try
        {
            String userStoreDomain = null;

            String provisioningClaimUri = context.getExternalIdP()
                    .getProvisioningUserStoreClaimURI();
            String provisioningUserStoreId = context.getExternalIdP().getProvisioningUserStoreId();

            if (provisioningUserStoreId != null)
                userStoreDomain = provisioningUserStoreId;
            else if (provisioningClaimUri != null) {
                userStoreDomain = (String)extAttributesValueMap.get(provisioningClaimUri);
            }

            ThreadLocalProvisioningServiceProvider serviceProvider = new ThreadLocalProvisioningServiceProvider();
            serviceProvider.setServiceProviderName(context.getSequenceConfig()
                    .getApplicationConfig().getApplicationName());
            serviceProvider.setJustInTimeProvisioning(true);
            serviceProvider.setClaimDialect(ApplicationConstants.LOCAL_IDP_DEFAULT_CLAIM_DIALECT);
            serviceProvider.setTenantDomain(context.getTenantDomain());

            IdentityApplicationManagementUtil.setThreadLocalProvisioningServiceProvider(serviceProvider);

            FrameworkUtils.getProvisioningHandler().handle(mappedRoles, subjectIdentifier, extAttributesValueMap, userStoreDomain, context
                    .getTenantDomain());

            UserProfileAdmin userProfileAdmin = UserProfileAdmin.getInstance();
            subjectIdentifier = MultitenantUtils.getTenantAwareUsername(subjectIdentifier);
            try
            {
                FrameworkUtils.startTenantFlow(context.getTenantDomain());
                PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(subjectIdentifier);
                String associatedID = userProfileAdmin.getNameAssociatedWith(context.getExternalIdP().getIdPName(), subjectIdentifier);

                if ((associatedID == null) || (associatedID.trim().length() == 0)) {
                    userProfileAdmin.associateID(context.getExternalIdP().getIdPName(), subjectIdentifier);
                    log.info("User association is created with the username");
                }
            } catch (UserProfileException e) {
                throw new FrameworkException(new StringBuilder().append("Error while associating local user ID for ").append(subjectIdentifier).toString(), e);
            }
            finally
            {
            }
        }
        catch (FrameworkException e) {
            log.error("User provisioning failed!", e);
        } finally {
            IdentityApplicationManagementUtil.resetThreadLocalProvisioningServiceProvider();
        }
    }

In there; we are creating an association with the same IDP identifier (which is the username). But; you can probably create association with different attributes if it is needed.

Step 2. Deployed extended jar file in to /repository/components/lib directory.

Step 3. Register custom step handler in repository/conf/identity/application-authentication.xml file.

<StepBasedSequenceHandler>org.wso2.carbon.identity.application.authentication.framework.handler.sequence.impl.CustomStepBasedSequenceHandler</StepBasedSequenceHandler>

Step 4. Restart the server

Step 3. Configure some Mandatory claims in SP configuration.  Here we have configured a single mandatory claim which is  “SOA Security Id”

Step 4. Try out the federation.

 

 

Step 5. User would be provisioned (Signup) with end user provided claims.

 

Discuss this article on Stack Overflow

Comments

  1. Hello,

    When doing federation we are doing JIT provisioning in our custom secondary userstore (custom osgi dropin and custom claimhandlers) in our WSO2 IS 5.0.0.
    When a user gets provisioned our userstore generates our own UUID. Would it be technically possible now in 5.3.0 to give back this UUID as a claim and return to the SP or even set it as the subject identifier/username(saml nameid) inside carbon instead of the one coming from federated idp. Up until 5.0.0 that we are using this seemed impossible because JIT provisioning happened after claim handling.

    Kind regards,
    Laurens

Leave a Reply

Your email address will not be published. Required fields are marked *