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();
}
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);
}
}
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());
}
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);
}
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);
}
Aggregations