@SuppressWarnings("unchecked")
    protected final AuthnRequest buildAuthnRequest(final SAML2MessageContext context,
                                                   final Endpoint assertionConsumerService,
                                                   final Endpoint ssoService) {
        val configContext = context.getConfigurationContext();
        val builder = (SAMLObjectBuilder<AuthnRequest>) this.builderFactory
            .getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME);
        val request = builder.buildObject();

        val comparisonType = getComparisonTypeEnumFromString(configContext.getComparisonType());
        if (comparisonType != null) {
            val authnContext = new RequestedAuthnContextBuilder().buildObject();
            authnContext.setComparison(comparisonType);

            if (configContext.getAuthnContextClassRefs() != null && !configContext.getAuthnContextClassRefs().isEmpty()) {
                val refs = authnContext.getAuthnContextClassRefs();
                configContext.getAuthnContextClassRefs().forEach(r -> refs.add(buildAuthnContextClassRef(r)));
            }
            request.setRequestedAuthnContext(authnContext);
        }

        val selfContext = context.getSAMLSelfEntityContext();

        request.setID(SAML2Utils.generateID());
        request.setIssuer(getIssuer(context, selfContext.getEntityId()));
        request.setIssueInstant(Instant.now().plusSeconds(this.issueInstantSkewSeconds));
        request.setVersion(SAMLVersion.VERSION_20);

        request.setIsPassive(configContext.isPassive());
        request.setForceAuthn(configContext.isForceAuth());

        if (StringUtils.isNotBlank(configContext.getProviderName())) {
            request.setProviderName(configContext.getProviderName());
        }

        if (configContext.getNameIdPolicyFormat() != null) {
            val nameIdPolicy = new NameIDPolicyBuilder().buildObject();
            if (configContext.isNameIdPolicyAllowCreate() != null) {
                nameIdPolicy.setAllowCreate(configContext.isNameIdPolicyAllowCreate());
            }
            nameIdPolicy.setFormat(configContext.getNameIdPolicyFormat());
            request.setNameIDPolicy(nameIdPolicy);
        }

        request.setDestination(ssoService.getLocation());
        if (configContext.getAssertionConsumerServiceIndex()  >= 0) {
            request.setAssertionConsumerServiceIndex(configContext.getAssertionConsumerServiceIndex());
        } else {
            request.setAssertionConsumerServiceURL(assertionConsumerService.getLocation());
            request.setProtocolBinding(assertionConsumerService.getBinding());
        }

        if (configContext.getAttributeConsumingServiceIndex() >= 0) {
            request.setAttributeConsumingServiceIndex(configContext.getAttributeConsumingServiceIndex());
        }

        val extensions = ((SAMLObjectBuilder<Extensions>) this.builderFactory
            .getBuilder(Extensions.DEFAULT_ELEMENT_NAME)).buildObject();

        if (!configContext.getSAML2Configuration().getRequestedServiceProviderAttributes().isEmpty()) {
            val attrBuilder =
                (SAMLObjectBuilder<RequestedAttribute>) this.builderFactory.getBuilder(RequestedAttribute.DEFAULT_ELEMENT_NAME);
            configContext.getSAML2Configuration().getRequestedServiceProviderAttributes().forEach(attribute -> {
                val requestAttribute = attrBuilder.buildObject(RequestedAttribute.DEFAULT_ELEMENT_NAME);
                requestAttribute.setIsRequired(attribute.isRequired());
                requestAttribute.setName(attribute.getName());
                requestAttribute.setFriendlyName(attribute.getFriendlyName());
                requestAttribute.setNameFormat(attribute.getNameFormat());
                extensions.getUnknownXMLObjects().add(requestAttribute);
            });
        }

        // Setting extensions if they are defined
        if (configContext.getSAML2Configuration().getAuthnRequestExtensions() != null) {
            extensions.getUnknownXMLObjects().addAll(configContext.getSAML2Configuration().getAuthnRequestExtensions() .get());
        }

        if (!extensions.getUnknownXMLObjects().isEmpty()) {
            request.setExtensions(extensions);
        }

        val givenIdPs = configContext.getSAML2Configuration().getScopingIdentityProviders();
        if (!givenIdPs.isEmpty()) {
            val scopingBuilder = (SAMLObjectBuilder<Scoping>) this.builderFactory
                .getBuilder(Scoping.DEFAULT_ELEMENT_NAME);
            val scoping = scopingBuilder.buildObject();
            val idpEntryBuilder = (SAMLObjectBuilder<IDPEntry>) this.builderFactory
                .getBuilder(IDPEntry.DEFAULT_ELEMENT_NAME);

            val idpListBuilder = (SAMLObjectBuilder<IDPList>) this.builderFactory
                .getBuilder(IDPList.DEFAULT_ELEMENT_NAME);
            scoping.setIDPList(idpListBuilder.buildObject());

            givenIdPs.forEach(idp -> {
                val idpEntry = idpEntryBuilder.buildObject();
                idpEntry.setProviderID(idp.getProviderId());
                idpEntry.setName(idp.getName());
                scoping.getIDPList().getIDPEntrys().add(idpEntry);
            });

            if (!scoping.getIDPList().getIDPEntrys().isEmpty()) {
                request.setScoping(scoping);
            }
        }
        return request;
    }
<p>buildAuthnRequest.</p>

@param context a {@link SAML2MessageContext} object
@param assertionConsumerService a {@link org.opensaml.saml.saml2.metadata.AssertionConsumerService} object
@param ssoService a {@link org.opensaml.saml.saml2.metadata.SingleSignOnService} object
@return a {@link AuthnRequest} object
pac4j-saml/src/main/java/org/pac4j/saml/sso/impl/SAML2AuthnRequestBuilder.java