Search in sources :

Example 1 with ProtocolMapper

use of org.keycloak.protocol.ProtocolMapper in project keycloak by keycloak.

the class SamlProtocol method authenticated.

@Override
public Response authenticated(AuthenticationSessionModel authSession, UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
    AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession();
    ClientModel client = clientSession.getClient();
    SamlClient samlClient = new SamlClient(client);
    String requestID = authSession.getClientNote(SAML_REQUEST_ID);
    String relayState = authSession.getClientNote(GeneralConstants.RELAY_STATE);
    String redirectUri = authSession.getRedirectUri();
    String responseIssuer = getResponseIssuer(realm);
    String nameIdFormat = getNameIdFormat(samlClient, authSession);
    int assertionLifespan = samlClient.getAssertionLifespan();
    SAML2LoginResponseBuilder builder = new SAML2LoginResponseBuilder();
    builder.requestID(requestID).destination(redirectUri).issuer(responseIssuer).assertionExpiration(assertionLifespan <= 0 ? realm.getAccessCodeLifespan() : assertionLifespan).subjectExpiration(assertionLifespan <= 0 ? realm.getAccessTokenLifespan() : assertionLifespan).sessionExpiration(realm.getSsoSessionMaxLifespan()).requestIssuer(clientSession.getClient().getClientId()).authMethod(JBossSAMLURIConstants.AC_UNSPECIFIED.get());
    String sessionIndex = SamlSessionUtils.getSessionIndex(clientSession);
    builder.sessionIndex(sessionIndex);
    if (!samlClient.includeAuthnStatement()) {
        builder.disableAuthnStatement(true);
    }
    builder.includeOneTimeUseCondition(samlClient.includeOneTimeUseCondition());
    List<ProtocolMapperProcessor<SAMLAttributeStatementMapper>> attributeStatementMappers = new LinkedList<>();
    List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> loginResponseMappers = new LinkedList<>();
    AtomicReference<ProtocolMapperProcessor<SAMLRoleListMapper>> roleListMapper = new AtomicReference<>(null);
    List<ProtocolMapperProcessor<SAMLNameIdMapper>> samlNameIdMappers = new LinkedList<>();
    ProtocolMapperUtils.getSortedProtocolMappers(session, clientSessionCtx).forEach(entry -> {
        ProtocolMapperModel mapping = entry.getKey();
        ProtocolMapper mapper = entry.getValue();
        if (mapper instanceof SAMLAttributeStatementMapper) {
            attributeStatementMappers.add(new ProtocolMapperProcessor<>((SAMLAttributeStatementMapper) mapper, mapping));
        }
        if (mapper instanceof SAMLLoginResponseMapper) {
            loginResponseMappers.add(new ProtocolMapperProcessor<>((SAMLLoginResponseMapper) mapper, mapping));
        }
        if (mapper instanceof SAMLRoleListMapper) {
            roleListMapper.set(new ProtocolMapperProcessor<>((SAMLRoleListMapper) mapper, mapping));
        }
        if (mapper instanceof SAMLNameIdMapper) {
            samlNameIdMappers.add(new ProtocolMapperProcessor<>((SAMLNameIdMapper) mapper, mapping));
        }
    });
    Document samlDocument = null;
    ResponseType samlModel = null;
    KeyManager keyManager = session.keys();
    KeyManager.ActiveRsaKey keys = keyManager.getActiveRsaKey(realm);
    boolean postBinding = isPostBinding(authSession);
    String keyName = samlClient.getXmlSigKeyInfoKeyNameTransformer().getKeyName(keys.getKid(), keys.getCertificate());
    String nameId = getSAMLNameId(samlNameIdMappers, nameIdFormat, session, userSession, clientSession);
    if (nameId == null) {
        return samlErrorMessage(null, samlClient, isPostBinding(authSession), redirectUri, JBossSAMLURIConstants.STATUS_INVALID_NAMEIDPOLICY, relayState);
    }
    builder.nameIdentifier(nameIdFormat, nameId);
    // save NAME_ID and format in clientSession as they may be persistent or
    // transient or email and not username
    // we'll need to send this back on a logout
    clientSession.setNote(SAML_NAME_ID, nameId);
    clientSession.setNote(SAML_NAME_ID_FORMAT, nameIdFormat);
    try {
        if ((!postBinding) && samlClient.requiresRealmSignature() && samlClient.addExtensionsElementWithKeyInfo()) {
            builder.addExtension(new KeycloakKeySamlExtensionGenerator(keyName));
        }
        samlModel = builder.buildModel();
        final AttributeStatementType attributeStatement = populateAttributeStatements(attributeStatementMappers, session, userSession, clientSession);
        populateRoles(roleListMapper.get(), session, userSession, clientSessionCtx, attributeStatement);
        // SAML Spec 2.7.3 AttributeStatement must contain one or more Attribute or EncryptedAttribute
        if (attributeStatement.getAttributes().size() > 0) {
            AssertionType assertion = samlModel.getAssertions().get(0).getAssertion();
            assertion.addStatement(attributeStatement);
        }
        samlModel = transformLoginResponse(loginResponseMappers, samlModel, session, userSession, clientSessionCtx);
    } catch (Exception e) {
        logger.error("failed", e);
        return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
    }
    JaxrsSAML2BindingBuilder bindingBuilder = new JaxrsSAML2BindingBuilder(session);
    bindingBuilder.relayState(relayState);
    if ("true".equals(clientSession.getNote(JBossSAMLURIConstants.SAML_HTTP_ARTIFACT_BINDING.get()))) {
        try {
            return buildArtifactAuthenticatedResponse(clientSession, redirectUri, samlModel, bindingBuilder);
        } catch (Exception e) {
            logger.error("failed", e);
            return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
        }
    }
    if (samlClient.requiresRealmSignature() || samlClient.requiresAssertionSignature()) {
        String canonicalization = samlClient.getCanonicalizationMethod();
        if (canonicalization != null) {
            bindingBuilder.canonicalizationMethod(canonicalization);
        }
        bindingBuilder.signatureAlgorithm(samlClient.getSignatureAlgorithm()).signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate());
        if (samlClient.requiresRealmSignature())
            bindingBuilder.signDocument();
        if (samlClient.requiresAssertionSignature())
            bindingBuilder.signAssertions();
    }
    if (samlClient.requiresEncryption()) {
        PublicKey publicKey = null;
        try {
            publicKey = SamlProtocolUtils.getEncryptionKey(client);
        } catch (Exception e) {
            logger.error("failed", e);
            return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
        }
        bindingBuilder.encrypt(publicKey);
    }
    try {
        samlDocument = builder.buildDocument(samlModel);
        return buildAuthenticatedResponse(clientSession, redirectUri, samlDocument, bindingBuilder);
    } catch (Exception e) {
        logger.error("failed", e);
        return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
    }
}
Also used : ProtocolMapper(org.keycloak.protocol.ProtocolMapper) SAMLNameIdMapper(org.keycloak.protocol.saml.mappers.SAMLNameIdMapper) Document(org.w3c.dom.Document) KeycloakKeySamlExtensionGenerator(org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator) SAMLAttributeStatementMapper(org.keycloak.protocol.saml.mappers.SAMLAttributeStatementMapper) SAMLLoginResponseMapper(org.keycloak.protocol.saml.mappers.SAMLLoginResponseMapper) SAML2LoginResponseBuilder(org.keycloak.saml.SAML2LoginResponseBuilder) KeyManager(org.keycloak.models.KeyManager) SAMLRoleListMapper(org.keycloak.protocol.saml.mappers.SAMLRoleListMapper) PublicKey(java.security.PublicKey) AttributeStatementType(org.keycloak.dom.saml.v2.assertion.AttributeStatementType) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) AtomicReference(java.util.concurrent.atomic.AtomicReference) AssertionType(org.keycloak.dom.saml.v2.assertion.AssertionType) LinkedList(java.util.LinkedList) ParsingException(org.keycloak.saml.common.exceptions.ParsingException) ProcessingException(org.keycloak.saml.common.exceptions.ProcessingException) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) IOException(java.io.IOException) ProtocolMapperModel(org.keycloak.models.ProtocolMapperModel) ArtifactResponseType(org.keycloak.dom.saml.v2.protocol.ArtifactResponseType) ResponseType(org.keycloak.dom.saml.v2.protocol.ResponseType) StatusResponseType(org.keycloak.dom.saml.v2.protocol.StatusResponseType) ClientModel(org.keycloak.models.ClientModel)

Example 2 with ProtocolMapper

use of org.keycloak.protocol.ProtocolMapper in project keycloak by keycloak.

the class RoleListMapper method mapRoles.

@Override
public void mapRoles(AttributeStatementType roleAttributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
    String single = mappingModel.getConfig().get(SINGLE_ROLE_ATTRIBUTE);
    boolean singleAttribute = Boolean.parseBoolean(single);
    List<SamlProtocol.ProtocolMapperProcessor<SAMLRoleNameMapper>> roleNameMappers = new LinkedList<>();
    AtomicReference<AttributeType> singleAttributeType = new AtomicReference<>(null);
    ProtocolMapperUtils.getSortedProtocolMappers(session, clientSessionCtx).forEach(entry -> {
        ProtocolMapperModel mapping = entry.getKey();
        ProtocolMapper mapper = entry.getValue();
        if (mapper instanceof SAMLRoleNameMapper) {
            roleNameMappers.add(new SamlProtocol.ProtocolMapperProcessor<>((SAMLRoleNameMapper) mapper, mapping));
        }
        if (mapper instanceof HardcodedRole) {
            AttributeType attributeType;
            if (singleAttribute) {
                if (singleAttributeType.get() == null) {
                    singleAttributeType.set(AttributeStatementHelper.createAttributeType(mappingModel));
                    roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(singleAttributeType.get()));
                }
                attributeType = singleAttributeType.get();
            } else {
                attributeType = AttributeStatementHelper.createAttributeType(mappingModel);
                roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attributeType));
            }
            attributeType.addAttributeValue(mapping.getConfig().get(HardcodedRole.ROLE_ATTRIBUTE));
        }
    });
    List<String> allRoleNames = clientSessionCtx.getRolesStream().map(roleModel -> roleNameMappers.stream().map(entry -> entry.mapper.mapName(entry.model, roleModel)).filter(Objects::nonNull).findFirst().orElse(roleModel.getName())).collect(Collectors.toList());
    for (String roleName : allRoleNames) {
        AttributeType attributeType;
        if (singleAttribute) {
            if (singleAttributeType.get() == null) {
                singleAttributeType.set(AttributeStatementHelper.createAttributeType(mappingModel));
                roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(singleAttributeType.get()));
            }
            attributeType = singleAttributeType.get();
        } else {
            attributeType = AttributeStatementHelper.createAttributeType(mappingModel);
            roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attributeType));
        }
        attributeType.addAttributeValue(roleName);
    }
}
Also used : ProtocolMapperModel(org.keycloak.models.ProtocolMapperModel) ProviderConfigProperty(org.keycloak.provider.ProviderConfigProperty) KeycloakSession(org.keycloak.models.KeycloakSession) SamlProtocol(org.keycloak.protocol.saml.SamlProtocol) HashMap(java.util.HashMap) UserSessionModel(org.keycloak.models.UserSessionModel) AtomicReference(java.util.concurrent.atomic.AtomicReference) Collectors(java.util.stream.Collectors) AttributeType(org.keycloak.dom.saml.v2.assertion.AttributeType) ArrayList(java.util.ArrayList) AttributeStatementType(org.keycloak.dom.saml.v2.assertion.AttributeStatementType) Objects(java.util.Objects) List(java.util.List) ClientSessionContext(org.keycloak.models.ClientSessionContext) Map(java.util.Map) ProtocolMapperUtils(org.keycloak.protocol.ProtocolMapperUtils) ProtocolMapper(org.keycloak.protocol.ProtocolMapper) LinkedList(java.util.LinkedList) AttributeStatementType(org.keycloak.dom.saml.v2.assertion.AttributeStatementType) AtomicReference(java.util.concurrent.atomic.AtomicReference) ProtocolMapper(org.keycloak.protocol.ProtocolMapper) SamlProtocol(org.keycloak.protocol.saml.SamlProtocol) LinkedList(java.util.LinkedList) ProtocolMapperModel(org.keycloak.models.ProtocolMapperModel) AttributeType(org.keycloak.dom.saml.v2.assertion.AttributeType) Objects(java.util.Objects)

Aggregations

LinkedList (java.util.LinkedList)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2 AttributeStatementType (org.keycloak.dom.saml.v2.assertion.AttributeStatementType)2 ProtocolMapperModel (org.keycloak.models.ProtocolMapperModel)2 ProtocolMapper (org.keycloak.protocol.ProtocolMapper)2 IOException (java.io.IOException)1 PublicKey (java.security.PublicKey)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 Objects (java.util.Objects)1 Collectors (java.util.stream.Collectors)1 AssertionType (org.keycloak.dom.saml.v2.assertion.AssertionType)1 AttributeType (org.keycloak.dom.saml.v2.assertion.AttributeType)1 ArtifactResponseType (org.keycloak.dom.saml.v2.protocol.ArtifactResponseType)1 ResponseType (org.keycloak.dom.saml.v2.protocol.ResponseType)1 StatusResponseType (org.keycloak.dom.saml.v2.protocol.StatusResponseType)1 AuthenticatedClientSessionModel (org.keycloak.models.AuthenticatedClientSessionModel)1 ClientModel (org.keycloak.models.ClientModel)1