Search in sources :

Example 41 with ClientModel

use of org.keycloak.models.ClientModel in project keycloak by keycloak.

the class SamlProtocol method isPostBinding.

protected boolean isPostBinding(AuthenticatedClientSessionModel clientSession) {
    ClientModel client = clientSession.getClient();
    SamlClient samlClient = new SamlClient(client);
    return SamlProtocol.SAML_POST_BINDING.equals(clientSession.getNote(SamlProtocol.SAML_BINDING)) || samlClient.forcePostBinding();
}
Also used : ClientModel(org.keycloak.models.ClientModel)

Example 42 with ClientModel

use of org.keycloak.models.ClientModel in project keycloak by keycloak.

the class SamlProtocol method sendError.

@Override
public Response sendError(AuthenticationSessionModel authSession, Error error) {
    try {
        ClientModel client = authSession.getClient();
        if ("true".equals(authSession.getClientNote(SAML_IDP_INITIATED_LOGIN))) {
            if (error == Error.CANCELLED_BY_USER) {
                UriBuilder builder = RealmsResource.protocolUrl(uriInfo).path(SamlService.class, "idpInitiatedSSO");
                Map<String, String> params = new HashMap<>();
                params.put("realm", realm.getName());
                params.put("protocol", LOGIN_PROTOCOL);
                params.put("client", client.getAttribute(SAML_IDP_INITIATED_SSO_URL_NAME));
                URI redirect = builder.buildFromMap(params);
                return Response.status(302).location(redirect).build();
            } else {
                return ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, translateErrorToIdpInitiatedErrorMessage(error));
            }
        } else {
            return samlErrorMessage(authSession, new SamlClient(client), isPostBinding(authSession), authSession.getRedirectUri(), translateErrorToSAMLStatus(error), authSession.getClientNote(GeneralConstants.RELAY_STATE));
        }
    } finally {
        new AuthenticationSessionManager(session).removeAuthenticationSession(realm, authSession, true);
    }
}
Also used : AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) ClientModel(org.keycloak.models.ClientModel) HashMap(java.util.HashMap) UriBuilder(javax.ws.rs.core.UriBuilder) KeycloakUriBuilder(org.keycloak.common.util.KeycloakUriBuilder) URI(java.net.URI)

Example 43 with ClientModel

use of org.keycloak.models.ClientModel in project keycloak by keycloak.

the class SamlProtocol method isLogoutPostBindingForClient.

protected boolean isLogoutPostBindingForClient(AuthenticatedClientSessionModel clientSession) {
    ClientModel client = clientSession.getClient();
    SamlClient samlClient = new SamlClient(client);
    String logoutPostUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE);
    String logoutRedirectUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE);
    if (logoutPostUrl == null || logoutPostUrl.trim().isEmpty()) {
        // if we don't have a redirect uri either, return true and default to the admin url + POST binding
        return (logoutRedirectUrl == null || logoutRedirectUrl.trim().isEmpty());
    }
    if (samlClient.forcePostBinding()) {
        // configured to force a post binding and post binding logout url is not null
        return true;
    }
    String bindingType = clientSession.getNote(SAML_BINDING);
    // if the login binding was POST, return true
    if (SAML_POST_BINDING.equals(bindingType))
        return true;
    // true if we don't have a redirect binding url, so use post binding, false for redirect binding
    return (logoutRedirectUrl == null || logoutRedirectUrl.trim().isEmpty());
}
Also used : ClientModel(org.keycloak.models.ClientModel)

Example 44 with ClientModel

use of org.keycloak.models.ClientModel in project keycloak by keycloak.

the class SamlService method idpInitiatedSSO.

@GET
@Path("clients/{client}")
@Produces(MediaType.TEXT_HTML_UTF_8)
public Response idpInitiatedSSO(@PathParam("client") String clientUrlName, @QueryParam("RelayState") String relayState) {
    event.event(EventType.LOGIN);
    CacheControlUtil.noBackButtonCacheControlHeader();
    ClientModel client = session.clients().searchClientsByAttributes(realm, Collections.singletonMap(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME, clientUrlName), 0, 1).findFirst().orElse(null);
    if (client == null) {
        event.error(Errors.CLIENT_NOT_FOUND);
        return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.CLIENT_NOT_FOUND);
    }
    if (!client.isEnabled()) {
        event.error(Errors.CLIENT_DISABLED);
        return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.CLIENT_DISABLED);
    }
    if (!isClientProtocolCorrect(client)) {
        event.error(Errors.INVALID_CLIENT);
        return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, "Wrong client protocol.");
    }
    session.getContext().setClient(client);
    AuthenticationSessionModel authSession = getOrCreateLoginSessionForIdpInitiatedSso(this.session, this.realm, client, relayState);
    if (authSession == null) {
        logger.error("SAML assertion consumer url not set up");
        event.error(Errors.INVALID_REDIRECT_URI);
        return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.INVALID_REDIRECT_URI);
    }
    return newBrowserAuthentication(authSession, false, false);
}
Also used : ClientModel(org.keycloak.models.ClientModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) Path(javax.ws.rs.Path) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET)

Example 45 with ClientModel

use of org.keycloak.models.ClientModel in project keycloak by keycloak.

the class SamlService method artifactResolve.

/**
 * Takes an artifact resolve message and returns the artifact response, if the artifact is found belonging to a session
 * of the issuer.
 * @param artifactResolveMessage The artifact resolve message sent by the client
 * @param artifactResolveHolder the document containing the artifact resolve message sent by the client
 * @return a Response containing the SOAP message with the ArifactResponse
 * @throws ParsingException
 * @throws ConfigurationException
 * @throws ProcessingException
 */
public Response artifactResolve(ArtifactResolveType artifactResolveMessage, SAMLDocumentHolder artifactResolveHolder) throws ParsingException, ConfigurationException, ProcessingException {
    logger.debug("Received artifactResolve message for artifact " + artifactResolveMessage.getArtifact() + "\n" + "Message: \n" + DocumentUtil.getDocumentAsString(artifactResolveHolder.getSamlDocument()));
    // Artifact from resolve request
    String artifact = artifactResolveMessage.getArtifact();
    if (artifact == null) {
        logger.errorf("Artifact to resolve was null");
        return emptyArtifactResponseMessage(artifactResolveMessage, null, JBossSAMLURIConstants.STATUS_REQUEST_DENIED.getUri());
    }
    ArtifactResolver artifactResolver = getArtifactResolver(artifact);
    if (artifactResolver == null) {
        logger.errorf("Cannot find ArtifactResolver for artifact %s", artifact);
        return emptyArtifactResponseMessage(artifactResolveMessage, null, JBossSAMLURIConstants.STATUS_REQUEST_DENIED.getUri());
    }
    // Obtain details of session that issued artifact and check if it corresponds to issuer of Resolve message
    SamlArtifactSessionMappingModel sessionMapping = getArtifactSessionMappingStore().get(artifact);
    if (sessionMapping == null) {
        logger.errorf("No data stored for artifact %s", artifact);
        return emptyArtifactResponseMessage(artifactResolveMessage, null);
    }
    UserSessionModel userSessionModel = session.sessions().getUserSession(realm, sessionMapping.getUserSessionId());
    if (userSessionModel == null) {
        logger.errorf("UserSession with id: %s, that corresponds to artifact: %s does not exist.", sessionMapping.getUserSessionId(), artifact);
        return emptyArtifactResponseMessage(artifactResolveMessage, null);
    }
    AuthenticatedClientSessionModel clientSessionModel = userSessionModel.getAuthenticatedClientSessions().get(sessionMapping.getClientSessionId());
    if (clientSessionModel == null) {
        logger.errorf("ClientSession with id: %s, that corresponds to artifact: %s and UserSession: %s does not exist.", sessionMapping.getClientSessionId(), artifact, sessionMapping.getUserSessionId());
        return emptyArtifactResponseMessage(artifactResolveMessage, null);
    }
    ClientModel clientModel = getAndCheckClientModel(sessionMapping.getClientSessionId(), artifactResolveMessage.getIssuer().getValue());
    SamlClient samlClient = new SamlClient(clientModel);
    // Check signature within ArtifactResolve request if client requires it
    if (samlClient.requiresClientSignature()) {
        try {
            SamlProtocolUtils.verifyDocumentSignature(clientModel, artifactResolveHolder.getSamlDocument());
        } catch (VerificationException e) {
            SamlService.logger.error("request validation failed", e);
            return emptyArtifactResponseMessage(artifactResolveMessage, clientModel);
        }
    }
    // Obtain artifactResponse from clientSessionModel
    String artifactResponseString;
    try {
        artifactResponseString = artifactResolver.resolveArtifact(clientSessionModel, artifact);
    } catch (ArtifactResolverProcessingException e) {
        logger.errorf(e, "Failed to resolve artifact: %s.", artifact);
        return emptyArtifactResponseMessage(artifactResolveMessage, clientModel);
    }
    // Artifact is successfully resolved, we can remove session mapping from storage
    getArtifactSessionMappingStore().remove(artifact);
    Document artifactResponseDocument = null;
    ArtifactResponseType artifactResponseType = null;
    try {
        SAMLDataMarshaller marshaller = new SAMLDataMarshaller();
        artifactResponseType = marshaller.deserialize(artifactResponseString, ArtifactResponseType.class);
        artifactResponseDocument = SamlProtocolUtils.convert(artifactResponseType);
    } catch (ParsingException | ConfigurationException | ProcessingException e) {
        logger.errorf(e, "Failed to obtain document from ArtifactResponseString: %s.", artifactResponseString);
        return emptyArtifactResponseMessage(artifactResolveMessage, clientModel);
    }
    // If clientSession is in LOGGING_OUT action, now we can move it to LOGGED_OUT
    if (CommonClientSessionModel.Action.LOGGING_OUT.name().equals(clientSessionModel.getAction())) {
        clientSessionModel.setAction(CommonClientSessionModel.Action.LOGGED_OUT.name());
        // If Keycloak sent LogoutResponse we need to also remove UserSession
        if (artifactResponseType.getAny() instanceof StatusResponseType && artifactResponseString.contains(JBossSAMLConstants.LOGOUT_RESPONSE.get())) {
            if (!UserSessionModel.State.LOGGED_OUT_UNCONFIRMED.equals(userSessionModel.getState())) {
                logger.warnf("Keycloak issued LogoutResponse for clientSession %s, however user session %s was not in LOGGED_OUT_UNCONFIRMED state.", clientSessionModel.getId(), userSessionModel.getId());
            }
            AuthenticationManager.finishUnconfirmedUserSession(session, realm, userSessionModel);
        }
    }
    return artifactResponseMessage(artifactResolveMessage, artifactResponseDocument, clientModel);
}
Also used : UserSessionModel(org.keycloak.models.UserSessionModel) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) Document(org.w3c.dom.Document) SAMLDataMarshaller(org.keycloak.broker.saml.SAMLDataMarshaller) StatusResponseType(org.keycloak.dom.saml.v2.protocol.StatusResponseType) SamlArtifactSessionMappingModel(org.keycloak.models.SamlArtifactSessionMappingModel) ClientModel(org.keycloak.models.ClientModel) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) ParsingException(org.keycloak.saml.common.exceptions.ParsingException) VerificationException(org.keycloak.common.VerificationException) ArtifactResponseType(org.keycloak.dom.saml.v2.protocol.ArtifactResponseType) ProcessingException(org.keycloak.saml.common.exceptions.ProcessingException)

Aggregations

ClientModel (org.keycloak.models.ClientModel)344 RealmModel (org.keycloak.models.RealmModel)148 UserModel (org.keycloak.models.UserModel)88 RoleModel (org.keycloak.models.RoleModel)74 KeycloakSession (org.keycloak.models.KeycloakSession)67 Test (org.junit.Test)64 UserSessionModel (org.keycloak.models.UserSessionModel)41 ResourceServer (org.keycloak.authorization.model.ResourceServer)39 Policy (org.keycloak.authorization.model.Policy)38 HashMap (java.util.HashMap)37 AuthorizationProvider (org.keycloak.authorization.AuthorizationProvider)36 AbstractTestRealmKeycloakTest (org.keycloak.testsuite.AbstractTestRealmKeycloakTest)34 ModelTest (org.keycloak.testsuite.arquillian.annotation.ModelTest)34 List (java.util.List)32 Map (java.util.Map)32 Path (javax.ws.rs.Path)29 LinkedList (java.util.LinkedList)28 ClientScopeModel (org.keycloak.models.ClientScopeModel)28 ArrayList (java.util.ArrayList)27 AuthenticatedClientSessionModel (org.keycloak.models.AuthenticatedClientSessionModel)27