/**
* Copyright (c) Codice Foundation
* <p>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package org.codice.ddf.security.filter.login;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivilegedExceptionAction;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.lang.StringUtils;
import org.apache.cxf.rs.security.saml.sso.SAMLProtocolResponseValidator;
import org.apache.cxf.ws.security.tokenstore.SecurityToken;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.CryptoFactory;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.saml.OpenSAMLUtil;
import org.apache.wss4j.common.saml.SamlAssertionWrapper;
import org.apache.wss4j.dom.WSDocInfo;
import org.apache.wss4j.dom.engine.WSSConfig;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.saml.WSSSAMLKeyInfoProcessor;
import org.apache.wss4j.dom.validate.Credential;
import org.apache.wss4j.dom.validate.SamlAssertionValidator;
import org.apache.wss4j.dom.validate.Validator;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.codice.ddf.configuration.SystemBaseUrl;
import org.codice.ddf.platform.util.XMLUtils;
import org.codice.ddf.security.handler.api.BaseAuthenticationToken;
import org.codice.ddf.security.handler.api.HandlerResult;
import org.codice.ddf.security.handler.api.InvalidSAMLReceivedException;
import org.codice.ddf.security.handler.api.SAMLAuthenticationToken;
import org.codice.ddf.security.policy.context.ContextPolicy;
import org.joda.time.DateTime;
import org.opensaml.core.xml.XMLObjectBuilderFactory;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.saml.common.SAMLObjectBuilder;
import org.opensaml.saml.common.SAMLVersion;
import org.opensaml.saml.saml2.core.Issuer;
import org.opensaml.saml.saml2.core.Response;
import org.opensaml.saml.saml2.core.Status;
import org.opensaml.saml.saml2.core.StatusCode;
import org.opensaml.saml.saml2.core.StatusMessage;
import org.opensaml.saml.saml2.core.SubjectConfirmation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import ddf.security.PropertiesLoader;
import ddf.security.SecurityConstants;
import ddf.security.Subject;
import ddf.security.assertion.SecurityAssertion;
import ddf.security.assertion.impl.SecurityAssertionImpl;
import ddf.security.common.SecurityTokenHolder;
import ddf.security.common.audit.SecurityLogger;
import ddf.security.http.SessionFactory;
import ddf.security.service.SecurityManager;
import ddf.security.service.SecurityServiceException;
/**
* Servlet filter that exchanges all incoming tokens for a SAML assertion via an
* STS.
*/
public class LoginFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(LoginFilter.class);
private static final String DDF_AUTHENTICATION_TOKEN = "ddf.security.token";
private static final ThreadLocal<DocumentBuilder> BUILDER = new ThreadLocal<DocumentBuilder>() {
@Override
protected DocumentBuilder initialValue() {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
} catch (ParserConfigurationException e) {
LOGGER.debug("Unable to configure features on document builder.", e);
}
return factory.newDocumentBuilder();
} catch (ParserConfigurationException ex) {
// This exception should not happen
throw new IllegalArgumentException("Unable to create new DocumentBuilder", ex);
}
}
};
private static SAMLObjectBuilder<Status> statusBuilder;
private static SAMLObjectBuilder<StatusCode> statusCodeBuilder;
private static SAMLObjectBuilder<StatusMessage> statusMessageBuilder;
private static SAMLObjectBuilder<Response> responseBuilder;
private static SAMLObjectBuilder<Issuer> issuerBuilder;
private static XMLObjectBuilderFactory builderFactory =
XMLObjectProviderRegistrySupport.getBuilderFactory();
private SecurityManager securityManager;
private String signaturePropertiesFile;
private Crypto signatureCrypto;
private Validator assertionValidator = new SamlAssertionValidator();
private SessionFactory sessionFactory;
/**
* Default expiration value is 31 minutes
*/
private int expirationTime = 31;
public LoginFilter() {
super();
}
/**
* Creates the SAML response that we use for validation against the CXF
* code.
*
* @param inResponseTo
* @param issuer
* @param status
* @return Response
*/
private static Response createSamlResponse(String inResponseTo, String issuer, Status status) {
if (responseBuilder == null) {
responseBuilder =
(SAMLObjectBuilder<Response>) builderFactory.getBuilder(Response.DEFAULT_ELEMENT_NAME);
}
Response response = responseBuilder.buildObject();
response.setID(UUID.randomUUID()
.toString());
response.setIssueInstant(new DateTime());
response.setInResponseTo(inResponseTo);
response.setIssuer(createIssuer(issuer));
response.setStatus(status);
response.setVersion(SAMLVersion.VERSION_20);
return response;
}
/**
* Creates the issuer object for the response.
*
* @param issuerValue
* @return Issuer
*/
private static Issuer createIssuer(String issuerValue) {
if (issuerBuilder == null) {
issuerBuilder =
(SAMLObjectBuilder<Issuer>) builderFactory.getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
}
Issuer issuer = issuerBuilder.buildObject();
issuer.setValue(issuerValue);
return issuer;
}
/**
* Creates the status object for the response.
*
* @param statusCodeValue
* @param statusMessage
* @return Status
*/
private static Status createStatus(String statusCodeValue, String statusMessage) {
if (statusBuilder == null) {
statusBuilder =
(SAMLObjectBuilder<Status>) builderFactory.getBuilder(Status.DEFAULT_ELEMENT_NAME);
}
if (statusCodeBuilder == null) {
statusCodeBuilder =
(SAMLObjectBuilder<StatusCode>) builderFactory.getBuilder(StatusCode.DEFAULT_ELEMENT_NAME);
}
if (statusMessageBuilder == null) {
statusMessageBuilder = (SAMLObjectBuilder<StatusMessage>) builderFactory.getBuilder(
StatusMessage.DEFAULT_ELEMENT_NAME);
}
Status status = statusBuilder.buildObject();
StatusCode statusCode = statusCodeBuilder.buildObject();
statusCode.setValue(statusCodeValue);
status.setStatusCode(statusCode);
if (statusMessage != null) {
StatusMessage statusMessageObject = statusMessageBuilder.buildObject();
statusMessageObject.setMessage(statusMessage);
status.setStatusMessage(statusMessageObject);
}
return status;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
LOGGER.debug("Starting LoginFilter.");
}
/**
* Validates an attached SAML assertion, or exchanges any other incoming
* token for a SAML assertion via the STS.
*
* @param request
* @param response
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(final ServletRequest request, final ServletResponse response,
final FilterChain chain) throws IOException, ServletException {
LOGGER.debug("Performing doFilter() on LoginFilter");
HttpServletRequest httpRequest = (HttpServletRequest) request;
if (request.getAttribute(ContextPolicy.NO_AUTH_POLICY) != null) {
LOGGER.debug("NO_AUTH_POLICY header was found, skipping login filter.");
chain.doFilter(request, response);
} else {
// perform validation
final Subject subject = validateRequest(httpRequest);
if (subject != null) {
httpRequest.setAttribute(SecurityConstants.SECURITY_SUBJECT, subject);
LOGGER.debug("Now performing request as user {} for {}",
subject.getPrincipal(),
StringUtils.isNotBlank(httpRequest.getContextPath()) ?
httpRequest.getContextPath() :
httpRequest.getServletPath());
subject.execute(() -> {
PrivilegedExceptionAction<Void> action = () -> {
chain.doFilter(request, response);
return null;
};
SecurityAssertion securityAssertion = subject.getPrincipals()
.oneByType(SecurityAssertion.class);
if (null != securityAssertion) {
HashSet emptySet = new HashSet();
javax.security.auth.Subject javaSubject = new javax.security.auth.Subject(
true,
securityAssertion.getPrincipals(),
emptySet,
emptySet);
javax.security.auth.Subject.doAs(javaSubject, action);
} else {
LOGGER.debug("Subject had no security assertion.");
}
return null;
});
} else {
LOGGER.debug("Could not attach subject to http request.");
}
}
}
private Subject validateRequest(final HttpServletRequest httpRequest)
throws IOException, ServletException {
Subject subject = null;
Object ddfAuthToken = httpRequest.getAttribute(DDF_AUTHENTICATION_TOKEN);
if (ddfAuthToken instanceof HandlerResult) {
HandlerResult result = (HandlerResult) ddfAuthToken;
BaseAuthenticationToken thisToken = result.getToken();
/*
* If the user has already authenticated they will have a valid SAML token. Validate
* that here and create the subject from the token.
*/
if (thisToken instanceof SAMLAuthenticationToken) {
subject = handleAuthenticationToken(httpRequest,
(SAMLAuthenticationToken) thisToken);
} else if (thisToken != null) {
subject = handleAuthenticationToken(httpRequest, thisToken);
}
}
return subject;
}
private Subject handleAuthenticationToken(HttpServletRequest httpRequest,
SAMLAuthenticationToken token) throws ServletException {
Subject subject;
try {
LOGGER.debug("Validating received SAML assertion.");
boolean wasReference = false;
boolean firstLogin = true;
if (token.isReference()) {
wasReference = true;
LOGGER.trace("Converting SAML reference to assertion");
Object sessionToken = httpRequest.getSession(false)
.getAttribute(SecurityConstants.SAML_ASSERTION);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Http Session assertion - class: {} loader: {}",
sessionToken.getClass()
.getName(),
sessionToken.getClass()
.getClassLoader());
LOGGER.trace("SecurityToken class: {} loader: {}",
SecurityToken.class.getName(),
SecurityToken.class.getClassLoader());
}
SecurityToken savedToken = null;
try {
savedToken =
((SecurityTokenHolder) sessionToken).getSecurityToken(token.getRealm());
} catch (ClassCastException e) {
httpRequest.getSession(false)
.invalidate();
}
if (savedToken != null) {
firstLogin = false;
token.replaceReferenece(savedToken);
}
if (token.isReference()) {
String msg = "Missing or invalid SAML assertion for provided reference.";
LOGGER.debug(msg);
throw new InvalidSAMLReceivedException(msg);
}
}
SAMLAuthenticationToken newToken = renewSecurityToken(httpRequest.getSession(false),
token);
SecurityToken securityToken;
if (newToken != null) {
firstLogin = false;
securityToken = (SecurityToken) newToken.getCredentials();
} else {
securityToken = (SecurityToken) token.getCredentials();
}
if (!wasReference) {
// wrap the token
SamlAssertionWrapper assertion = new SamlAssertionWrapper(securityToken.getToken());
// get the crypto junk
Crypto crypto = getSignatureCrypto();
Response samlResponse = createSamlResponse(httpRequest.getRequestURI(),
assertion.getIssuerString(),
createStatus(SAMLProtocolResponseValidator.SAML2_STATUSCODE_SUCCESS, null));
BUILDER.get()
.reset();
Document doc = BUILDER.get()
.newDocument();
Element policyElement = OpenSAMLUtil.toDom(samlResponse, doc);
doc.appendChild(policyElement);
Credential credential = new Credential();
credential.setSamlAssertion(assertion);
RequestData requestData = new RequestData();
requestData.setSigVerCrypto(crypto);
WSSConfig wssConfig = WSSConfig.getNewInstance();
requestData.setWssConfig(wssConfig);
X509Certificate[] x509Certs = (X509Certificate[]) httpRequest.getAttribute(
"javax.servlet.request.X509Certificate");
requestData.setTlsCerts(x509Certs);
validateHolderOfKeyConfirmation(assertion, x509Certs);
if (assertion.isSigned()) {
// Verify the signature
WSSSAMLKeyInfoProcessor wsssamlKeyInfoProcessor = new WSSSAMLKeyInfoProcessor(
requestData,
new WSDocInfo(samlResponse.getDOM()
.getOwnerDocument()));
assertion.verifySignature(wsssamlKeyInfoProcessor, crypto);
assertion.parseSubject(new WSSSAMLKeyInfoProcessor(requestData,
new WSDocInfo(samlResponse.getDOM()
.getOwnerDocument())),
requestData.getSigVerCrypto(),
requestData.getCallbackHandler());
}
// Validate the Assertion & verify trust in the signature
assertionValidator.validate(credential, requestData);
}
// if it is all good, then we'll create our subject
subject = securityManager.getSubject(securityToken);
if (firstLogin) {
boolean hasSecurityAuditRole = Arrays.stream(System.getProperty(
"security.audit.roles")
.split(","))
.filter(subject::hasRole)
.findFirst()
.isPresent();
if (hasSecurityAuditRole) {
SecurityLogger.audit("Subject has logged in with admin privileges", subject);
}
}
if (!wasReference && firstLogin) {
addSamlToSession(httpRequest, token.getRealm(), securityToken);
}
} catch (SecurityServiceException e) {
LOGGER.debug("Unable to get subject from SAML request.", e);
throw new ServletException(e);
} catch (WSSecurityException e) {
LOGGER.debug("Unable to read/validate security token from request.", e);
throw new ServletException(e);
}
return subject;
}
private void validateHolderOfKeyConfirmation(SamlAssertionWrapper assertion,
X509Certificate[] x509Certs) throws SecurityServiceException {
List<String> confirmationMethods = assertion.getConfirmationMethods();
boolean hasHokMethod = false;
for (String method : confirmationMethods) {
if (OpenSAMLUtil.isMethodHolderOfKey(method)) {
hasHokMethod = true;
}
}
if (hasHokMethod) {
if (x509Certs != null && x509Certs.length > 0) {
List<SubjectConfirmation> subjectConfirmations = assertion.getSaml2()
.getSubject()
.getSubjectConfirmations();
for (SubjectConfirmation subjectConfirmation : subjectConfirmations) {
if (OpenSAMLUtil.isMethodHolderOfKey(subjectConfirmation.getMethod())) {
Element dom = subjectConfirmation.getSubjectConfirmationData()
.getDOM();
Node keyInfo = dom.getFirstChild();
Node x509Data = keyInfo.getFirstChild();
Node dataNode = x509Data.getFirstChild();
Node dataText = dataNode.getFirstChild();
X509Certificate tlsCertificate = x509Certs[0];
if (dataNode.getLocalName()
.equals("X509Certificate")) {
String textContent = dataText.getTextContent();
byte[] byteValue = Base64.getMimeDecoder()
.decode(textContent);
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert =
(X509Certificate) cf.generateCertificate(new ByteArrayInputStream(
byteValue));
//check that the certificate is still valid
cert.checkValidity();
//HoK spec section 2.5:
//relying party MUST ensure that the certificate bound to the assertion matches the X.509 certificate in its possession.
//Matching is done by comparing the base64-decoded certificates, or the hash values of the base64-decoded certificates, byte-for-byte.
//if the certs aren't the same, verify
if (!tlsCertificate.equals(cert)) {
//verify that the cert was signed by the same private key as the TLS cert
cert.verify(tlsCertificate.getPublicKey());
}
} catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException | SignatureException | NoSuchProviderException e) {
throw new SecurityServiceException(
"Unable to validate Holder of Key assertion with certificate.");
}
} else if (dataNode.getLocalName()
.equals("X509SubjectName")) {
String textContent = dataText.getTextContent();
//HoK spec section 2.5:
//relying party MUST ensure that the subject distinguished name (DN) bound to the assertion matches the DN bound to the X.509 certificate.
//If, however, the relying party does not trust the certificate issuer to issue such a DN, the attesting entity is not confirmed and the relying party SHOULD disregard the assertion.
if (!tlsCertificate.getSubjectDN()
.getName()
.equals(textContent)) {
throw new SecurityServiceException(
"Unable to validate Holder of Key assertion with subject DN.");
}
} else if (dataNode.getLocalName()
.equals("X509IssuerSerial")) {
//we have no way to support this confirmation type so we have to throw an error
throw new SecurityServiceException(
"Unable to validate Holder of Key assertion with issuer serial. NOT SUPPORTED");
} else if (dataNode.getLocalName()
.equals("X509SKI")) {
String textContent = dataText.getTextContent();
byte[] tlsSKI = tlsCertificate.getExtensionValue("2.5.29.14");
byte[] assertionSKI = Base64.getMimeDecoder()
.decode(textContent);
if (tlsSKI != null && tlsSKI.length > 0) {
ASN1OctetString tlsOs = ASN1OctetString.getInstance(tlsSKI);
ASN1OctetString assertionOs = ASN1OctetString.getInstance(
assertionSKI);
SubjectKeyIdentifier tlsSubjectKeyIdentifier =
SubjectKeyIdentifier.getInstance(tlsOs.getOctets());
SubjectKeyIdentifier assertSubjectKeyIdentifier =
SubjectKeyIdentifier.getInstance(assertionOs.getOctets());
//HoK spec section 2.5:
//relying party MUST ensure that the value bound to the assertion matches the Subject Key Identifier (SKI) extension bound to the X.509 certificate.
//Matching is done by comparing the base64-decoded SKI values byte-for-byte. If the X.509 certificate does not contain an SKI extension,
//the attesting entity is not confirmed and the relying party SHOULD disregard the assertion.
if (!Arrays.equals(tlsSubjectKeyIdentifier.getKeyIdentifier(),
assertSubjectKeyIdentifier.getKeyIdentifier())) {
throw new SecurityServiceException(
"Unable to validate Holder of Key assertion with subject key identifier.");
}
} else {
throw new SecurityServiceException(
"Unable to validate Holder of Key assertion with subject key identifier.");
}
}
}
}
} else {
throw new SecurityServiceException(
"Holder of Key assertion, must be used with 2-way TLS.");
}
}
}
private SAMLAuthenticationToken renewSecurityToken(HttpSession session,
SAMLAuthenticationToken savedToken) throws ServletException, WSSecurityException {
if (session != null) {
SecurityAssertion savedAssertion =
new SecurityAssertionImpl(((SecurityToken) savedToken.getCredentials()));
if (savedAssertion.getIssuer() != null && !savedAssertion.getIssuer()
.equals(SystemBaseUrl.getHost())) {
return null;
}
if (savedAssertion.getNotOnOrAfter() == null) {
return null;
}
long afterMil = savedAssertion.getNotOnOrAfter()
.getTime();
long timeoutMillis = (afterMil - System.currentTimeMillis());
if (timeoutMillis <= 0) {
throw new InvalidSAMLReceivedException("SAML assertion has expired.");
}
if (timeoutMillis <= 60000) { // within 60 seconds
try {
LOGGER.debug("Attempting to refresh user's SAML assertion.");
Subject subject = securityManager.getSubject(savedToken);
LOGGER.debug("Refresh of user assertion successful");
for (Object principal : subject.getPrincipals()) {
if (principal instanceof SecurityAssertion) {
SecurityToken token =
((SecurityAssertion) principal).getSecurityToken();
SAMLAuthenticationToken samlAuthenticationToken =
new SAMLAuthenticationToken((java.security.Principal) savedToken.getPrincipal(),
token,
savedToken.getRealm());
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Setting session token - class: {} classloader: {}",
token.getClass()
.getName(),
token.getClass()
.getClassLoader());
}
((SecurityTokenHolder) session.getAttribute(SecurityConstants.SAML_ASSERTION)).addSecurityToken(
savedToken.getRealm(),
token);
LOGGER.debug("Saved new user assertion to session.");
return samlAuthenticationToken;
}
}
} catch (SecurityServiceException e) {
LOGGER.debug(
"Unable to refresh user's SAML assertion. User will log out prematurely.",
e);
session.invalidate();
} catch (Exception e) {
LOGGER.info("Unhandled exception occurred.", e);
session.invalidate();
}
}
}
return null;
}
private Subject handleAuthenticationToken(HttpServletRequest httpRequest,
BaseAuthenticationToken token) throws ServletException {
Subject subject;
HttpSession session = sessionFactory.getOrCreateSession(httpRequest);
//if we already have an assertion inside the session and it has not expired, then use that instead
SecurityToken sessionToken = getSecurityToken(session, token.getRealm());
if (sessionToken == null) {
/*
* The user didn't have a SAML token from a previous authentication, but they do have the
* credentials to log in - perform that action here.
*/
try {
// login with the specified authentication credentials (AuthenticationToken)
subject = securityManager.getSubject(token);
for (Object principal : subject.getPrincipals()
.asList()) {
if (principal instanceof SecurityAssertion) {
if (LOGGER.isTraceEnabled()) {
Element samlToken = ((SecurityAssertion) principal).getSecurityToken()
.getToken();
LOGGER.trace("SAML Assertion returned: {}",
XMLUtils.prettyFormat(samlToken));
}
SecurityToken securityToken =
((SecurityAssertion) principal).getSecurityToken();
addSamlToSession(httpRequest, token.getRealm(), securityToken);
}
}
} catch (SecurityServiceException e) {
LOGGER.debug("Unable to get subject from auth request.", e);
throw new ServletException(e);
}
} else {
LOGGER.trace("Creating SAML authentication token with session.");
SAMLAuthenticationToken samlToken = new SAMLAuthenticationToken(null,
session.getId(),
token.getRealm());
return handleAuthenticationToken(httpRequest, samlToken);
}
return subject;
}
private SecurityToken getSecurityToken(HttpSession session, String realm) {
if (session.getAttribute(SecurityConstants.SAML_ASSERTION) == null) {
LOGGER.debug(
"Security token holder missing from session. New session created improperly.");
return null;
}
SecurityTokenHolder tokenHolder = ((SecurityTokenHolder) session.getAttribute(
SecurityConstants.SAML_ASSERTION));
SecurityToken token = tokenHolder.getSecurityToken(realm);
if (token != null) {
SecurityAssertionImpl assertion = new SecurityAssertionImpl(token);
if (!assertion.isPresentlyValid()) {
LOGGER.debug("Session SAML token is invalid. Removing from session.");
tokenHolder.remove(realm);
return null;
}
}
return token;
}
private void addSecurityToken(HttpSession session, String realm, SecurityToken token) {
SecurityTokenHolder holder =
(SecurityTokenHolder) session.getAttribute(SecurityConstants.SAML_ASSERTION);
holder.addSecurityToken(realm, token);
}
/**
* Adds SAML assertion to HTTP session.
*
* @param httpRequest the http request object for this request
* @param securityToken the SecurityToken object representing the SAML assertion
*/
private void addSamlToSession(HttpServletRequest httpRequest, String realm,
SecurityToken securityToken) {
if (securityToken == null) {
LOGGER.debug("Cannot add null security token to session.");
return;
}
HttpSession session = sessionFactory.getOrCreateSession(httpRequest);
SecurityToken sessionToken = getSecurityToken(session, realm);
if (sessionToken == null) {
addSecurityToken(session, realm, securityToken);
}
int minutes = getExpirationTime();
//we just want to set this to some non-zero value if the configuration is messed up
int seconds = 60;
if (minutes > 0) {
seconds = minutes * 60;
}
session.setMaxInactiveInterval(seconds);
}
/**
* Returns a Crypto object initialized against the system signature
* properties.
*
* @return Crypto
*/
private Crypto getSignatureCrypto() {
if (signatureCrypto == null && signaturePropertiesFile != null) {
Properties sigProperties = PropertiesLoader.loadProperties(signaturePropertiesFile);
if (sigProperties == null) {
LOGGER.trace("Cannot load signature properties using: {}", signaturePropertiesFile);
return null;
}
try {
signatureCrypto = CryptoFactory.getInstance(sigProperties);
} catch (WSSecurityException ex) {
LOGGER.trace("Error in loading the signature Crypto object.", ex);
return null;
}
}
return signatureCrypto;
}
@Override
public void destroy() {
LOGGER.debug("Destroying log in filter");
BUILDER.remove();
}
public SecurityManager getSecurityManager() {
return securityManager;
}
public void setSecurityManager(SecurityManager securityManager) {
this.securityManager = securityManager;
}
public void setSignaturePropertiesFile(String signaturePropertiesFile) {
this.signaturePropertiesFile = signaturePropertiesFile;
}
/**
* Returns session expiration time in minutes.
*
* @return minutes for session expiration
*/
public int getExpirationTime() {
return expirationTime;
}
/**
* Sets session expiration time in minutes
*
* @param expirationTime - time in minutes
*/
public void setExpirationTime(int expirationTime) {
this.expirationTime = expirationTime;
}
}