use of org.keycloak.adapters.saml.SamlSession in project keycloak by keycloak.
the class AbstractSamlAuthenticationHandler method handleLoginResponse.
protected AuthOutcome handleLoginResponse(SAMLDocumentHolder responseHolder, boolean postBinding, OnSessionCreated onCreateSession) {
if (!sessionStore.isLoggingIn()) {
log.warn("Adapter obtained LoginResponse, however containers session is not aware of sending any request. " + "This may be because the session cookies created by container are not properly configured " + "with SameSite settings. Refer to KEYCLOAK-14103 for more details.");
}
final ResponseType responseType = (ResponseType) responseHolder.getSamlObject();
AssertionType assertion = null;
if (!isSuccessfulSamlResponse(responseType) || responseType.getAssertions() == null || responseType.getAssertions().isEmpty()) {
return failed(createAuthChallenge403(responseType));
}
try {
assertion = AssertionUtil.getAssertion(responseHolder, responseType, deployment.getDecryptionKey());
ConditionsValidator.Builder cvb = new ConditionsValidator.Builder(assertion.getID(), assertion.getConditions(), destinationValidator);
try {
cvb.clockSkewInMillis(deployment.getIDP().getAllowedClockSkew());
cvb.addAllowedAudience(URI.create(deployment.getEntityID()));
if (responseType.getDestination() != null) {
// getDestination has been validated to match request URL already so it matches SAML endpoint
cvb.addAllowedAudience(URI.create(responseType.getDestination()));
}
} catch (IllegalArgumentException ex) {
// warning has been already emitted in DeploymentBuilder
}
if (!cvb.build().isValid()) {
return initiateLogin();
}
} catch (Exception e) {
log.error("Error extracting SAML assertion: " + e.getMessage());
return failed(CHALLENGE_EXTRACTION_FAILURE);
}
Element assertionElement = null;
if (deployment.getIDP().getSingleSignOnService().validateAssertionSignature()) {
try {
assertionElement = getAssertionFromResponse(responseHolder);
if (!AssertionUtil.isSignatureValid(assertionElement, deployment.getIDP().getSignatureValidationKeyLocator())) {
log.error("Failed to verify saml assertion signature");
return failed(CHALLENGE_INVALID_SIGNATURE);
}
} catch (Exception e) {
log.error("Error processing validation of SAML assertion: " + e.getMessage());
return failed(CHALLENGE_EXTRACTION_FAILURE);
}
}
SubjectType subject = assertion.getSubject();
SubjectType.STSubType subType = subject.getSubType();
NameIDType subjectNameID = subType == null ? null : (NameIDType) subType.getBaseID();
String principalName = subjectNameID == null ? null : subjectNameID.getValue();
Set<String> roles = new HashSet<>();
MultivaluedHashMap<String, String> attributes = new MultivaluedHashMap<>();
MultivaluedHashMap<String, String> friendlyAttributes = new MultivaluedHashMap<>();
Set<StatementAbstractType> statements = assertion.getStatements();
for (StatementAbstractType statement : statements) {
if (statement instanceof AttributeStatementType) {
AttributeStatementType attributeStatement = (AttributeStatementType) statement;
List<AttributeStatementType.ASTChoiceType> attList = attributeStatement.getAttributes();
for (AttributeStatementType.ASTChoiceType obj : attList) {
AttributeType attr = obj.getAttribute();
if (isRole(attr)) {
List<Object> attributeValues = attr.getAttributeValue();
if (attributeValues != null) {
for (Object attrValue : attributeValues) {
String role = getAttributeValue(attrValue);
log.debugv("Add role: {0}", role);
roles.add(role);
}
}
} else {
List<Object> attributeValues = attr.getAttributeValue();
if (attributeValues != null) {
for (Object attrValue : attributeValues) {
String value = getAttributeValue(attrValue);
if (attr.getName() != null) {
attributes.add(attr.getName(), value);
}
if (attr.getFriendlyName() != null) {
friendlyAttributes.add(attr.getFriendlyName(), value);
}
}
}
}
}
}
}
if (deployment.getPrincipalNamePolicy() == SamlDeployment.PrincipalNamePolicy.FROM_ATTRIBUTE) {
if (deployment.getPrincipalAttributeName() != null) {
String attribute = attributes.getFirst(deployment.getPrincipalAttributeName());
if (attribute != null)
principalName = attribute;
else {
attribute = friendlyAttributes.getFirst(deployment.getPrincipalAttributeName());
if (attribute != null)
principalName = attribute;
}
}
}
// use the configured role mappings provider to map roles if necessary.
if (deployment.getRoleMappingsProvider() != null) {
roles = deployment.getRoleMappingsProvider().map(principalName, roles);
}
// roles should also be there as regular attributes
// this mainly required for elytron and its ABAC nature
attributes.put(DEFAULT_ROLE_ATTRIBUTE_NAME, new ArrayList<>(roles));
AuthnStatementType authn = null;
for (Object statement : assertion.getStatements()) {
if (statement instanceof AuthnStatementType) {
authn = (AuthnStatementType) statement;
break;
}
}
URI nameFormat = subjectNameID == null ? null : subjectNameID.getFormat();
String nameFormatString = nameFormat == null ? JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get() : nameFormat.toString();
if (deployment.isKeepDOMAssertion() && assertionElement == null) {
// obtain the assertion from the response to add the DOM document to the principal
assertionElement = getAssertionFromResponseNoException(responseHolder);
}
final SamlPrincipal principal = new SamlPrincipal(assertion, deployment.isKeepDOMAssertion() ? getAssertionDocumentFromElement(assertionElement) : null, principalName, principalName, nameFormatString, attributes, friendlyAttributes);
final String sessionIndex = authn == null ? null : authn.getSessionIndex();
final XMLGregorianCalendar sessionNotOnOrAfter = authn == null ? null : authn.getSessionNotOnOrAfter();
SamlSession account = new SamlSession(principal, roles, sessionIndex, sessionNotOnOrAfter);
sessionStore.saveAccount(account);
onCreateSession.onSessionCreated(account);
// redirect to original request, it will be restored
String redirectUri = sessionStore.getRedirectUri();
if (redirectUri != null) {
facade.getResponse().setHeader("Location", redirectUri);
facade.getResponse().setStatus(302);
facade.getResponse().end();
} else {
log.debug("IDP initiated invocation");
}
log.debug("AUTHENTICATED authn");
return AuthOutcome.AUTHENTICATED;
}
use of org.keycloak.adapters.saml.SamlSession in project keycloak by keycloak.
the class AbstractSamlAuthenticator method validateRequest.
@Override
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException {
if (log.isTraceEnabled()) {
log.trace("*** authenticate");
}
Request request = resolveRequest(req);
JettyHttpFacade facade = new JettyHttpFacade(request, (HttpServletResponse) res);
SamlDeployment deployment = deploymentContext.resolveDeployment(facade);
if (deployment == null || !deployment.isConfigured()) {
log.debug("*** deployment isn't configured return false");
return Authentication.UNAUTHENTICATED;
}
boolean isEndpoint = request.getRequestURI().substring(request.getContextPath().length()).endsWith("/saml");
if (!mandatory && !isEndpoint)
return new DeferredAuthentication(this);
JettySamlSessionStore tokenStore = getTokenStore(request, facade, deployment);
SamlAuthenticator authenticator = null;
if (isEndpoint) {
authenticator = new SamlAuthenticator(facade, deployment, tokenStore) {
@Override
protected void completeAuthentication(SamlSession account) {
}
@Override
protected SamlAuthenticationHandler createBrowserHandler(HttpFacade facade, SamlDeployment deployment, SamlSessionStore sessionStore) {
return new SamlEndpoint(facade, deployment, sessionStore);
}
};
} else {
authenticator = new SamlAuthenticator(facade, deployment, tokenStore) {
@Override
protected void completeAuthentication(SamlSession account) {
}
@Override
protected SamlAuthenticationHandler createBrowserHandler(HttpFacade facade, SamlDeployment deployment, SamlSessionStore sessionStore) {
return new BrowserHandler(facade, deployment, sessionStore);
}
};
}
AuthOutcome outcome = authenticator.authenticate();
if (outcome == AuthOutcome.AUTHENTICATED) {
if (facade.isEnded()) {
return Authentication.SEND_SUCCESS;
}
SamlSession samlSession = tokenStore.getAccount();
Authentication authentication = register(request, samlSession);
return authentication;
}
if (outcome == AuthOutcome.LOGGED_OUT) {
logoutCurrent(request);
if (deployment.getLogoutPage() != null) {
forwardToLogoutPage(request, (HttpServletResponse) res, deployment);
}
return Authentication.SEND_CONTINUE;
}
AuthChallenge challenge = authenticator.getChallenge();
if (challenge != null) {
challenge.challenge(facade);
}
return Authentication.SEND_CONTINUE;
}
use of org.keycloak.adapters.saml.SamlSession in project keycloak by keycloak.
the class SamlFilter method doFilter.
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
ServletHttpFacade facade = new ServletHttpFacade(request, response);
SamlDeployment deployment = deploymentContext.resolveDeployment(facade);
if (deployment == null || !deployment.isConfigured()) {
response.sendError(403);
log.fine("deployment not configured");
return;
}
FilterSamlSessionStore tokenStore = new FilterSamlSessionStore(request, facade, 100000, idMapper, deployment);
boolean isEndpoint = request.getRequestURI().substring(request.getContextPath().length()).endsWith("/saml");
SamlAuthenticator authenticator;
if (isEndpoint) {
authenticator = new SamlAuthenticator(facade, deployment, tokenStore) {
@Override
protected void completeAuthentication(SamlSession account) {
}
@Override
protected SamlAuthenticationHandler createBrowserHandler(HttpFacade facade, SamlDeployment deployment, SamlSessionStore sessionStore) {
return new SamlEndpoint(facade, deployment, sessionStore);
}
};
} else {
authenticator = new SamlAuthenticator(facade, deployment, tokenStore) {
@Override
protected void completeAuthentication(SamlSession account) {
}
@Override
protected SamlAuthenticationHandler createBrowserHandler(HttpFacade facade, SamlDeployment deployment, SamlSessionStore sessionStore) {
return new BrowserHandler(facade, deployment, sessionStore);
}
};
}
AuthOutcome outcome = authenticator.authenticate();
if (outcome == AuthOutcome.AUTHENTICATED) {
log.fine("AUTHENTICATED");
if (facade.isEnded()) {
return;
}
HttpServletRequestWrapper wrapper = tokenStore.getWrap();
chain.doFilter(wrapper, res);
return;
}
if (outcome == AuthOutcome.LOGGED_OUT) {
tokenStore.logoutAccount();
String logoutPage = deployment.getLogoutPage();
if (logoutPage != null) {
if (PROTOCOL_PATTERN.matcher(logoutPage).find()) {
response.sendRedirect(logoutPage);
log.log(Level.FINE, "Redirected to logout page {0}", logoutPage);
} else {
RequestDispatcher disp = req.getRequestDispatcher(logoutPage);
disp.forward(req, res);
}
return;
}
chain.doFilter(req, res);
return;
}
AuthChallenge challenge = authenticator.getChallenge();
if (challenge != null) {
log.fine("challenge");
challenge.challenge(facade);
return;
}
if (deployment.isIsPassive() && outcome == AuthOutcome.NOT_AUTHENTICATED) {
log.fine("PASSIVE_NOT_AUTHENTICATED");
if (facade.isEnded()) {
return;
}
chain.doFilter(req, res);
return;
}
if (!facade.isEnded()) {
response.sendError(403);
}
}
use of org.keycloak.adapters.saml.SamlSession in project keycloak by keycloak.
the class JettySamlSessionStore method isLoggedIn.
@Override
public boolean isLoggedIn() {
HttpSession session = request.getSession(false);
if (session == null) {
log.debug("session was null, returning false");
return false;
}
SamlSession samlSession = SamlUtil.validateSamlSession(session.getAttribute(SamlSession.class.getName()), deployment);
if (samlSession == null) {
return false;
}
restoreRequest();
return true;
}
use of org.keycloak.adapters.saml.SamlSession in project keycloak by keycloak.
the class JettySamlSessionStore method saveAccount.
@Override
public void saveAccount(SamlSession account) {
HttpSession session = request.getSession(true);
session.setAttribute(SamlSession.class.getName(), account);
idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), changeSessionId(session));
}
Aggregations