Commit 4cbc5551 authored by Gradl, Tobias's avatar Gradl, Tobias
Browse files

720: Implement attribute checker

Task-Url: https://minfba.de.dariah.eu/mantisbt/view.php?id=720
parent f90580d1
......@@ -17,7 +17,8 @@ public class UserCredentialsException extends AuthenticationException {
public enum UserCredentialsExceptionTypes {
ID_ATTRIBUTE_NOT_PROVIDED,
NAME_ID_NOT_PROVIDED,
CREDENTIALS_NOT_AVAILABLE
CREDENTIALS_NOT_AVAILABLE,
ATTRIBUTESET_INCOMPLETE
}
public User getUser() { return user; }
......
package eu.dariah.de.dariahsp.saml.attributequery;
import java.util.ArrayList;
import java.util.List;
import org.opensaml.saml2.core.Attribute;
import org.slf4j.Logger;
......@@ -8,6 +9,8 @@ import org.springframework.security.saml.SAMLCredential;
import eu.dariah.de.dariahsp.Constants.AUTHENTICATION_STAGE;
import eu.dariah.de.dariahsp.Constants.REQUIRED_ATTRIBUTE_CHECKLOGIC;
import eu.dariah.de.dariahsp.exceptions.UserCredentialsException;
import eu.dariah.de.dariahsp.exceptions.UserCredentialsException.UserCredentialsExceptionTypes;
import eu.dariah.de.dariahsp.saml.attributequery.options.SAMLAttributeGroup;
import eu.dariah.de.dariahsp.saml.attributequery.options.SAMLAttributeQueryExclusionOptions;
import eu.dariah.de.dariahsp.saml.attributequery.options.SAMLAttributeQueryOptions;
......@@ -39,16 +42,20 @@ public class SAMLAttributeAggregationService {
public SAMLCredential aggregateIfRequired(SAMLCredential credential) {
SAMLAggregatedCredential aggCredential = new SAMLAggregatedCredential(credential, null, hasAllReqAttributes(credential.getAttributes(), AUTHENTICATION_STAGE.ATTRIBUTES));
if (!queryOptions.isPerformAggregation()) {
return credential;
return aggCredential;
}
boolean queryRequired = true;
if (queryOptions.getExclusionOptions()!=null) {
if (aggCredential.isHasAllAttributes()) {
queryRequired = false;
} else if (queryOptions.getExclusionOptions()!=null) {
for (SAMLAttributeQueryExclusionOptions exOpt : queryOptions.getExclusionOptions()) {
if (exOpt.getExcludedEndpoints()!=null && exOpt.getExcludedEndpoints().contains(credential.getRemoteEntityID())) {
if (exOpt.isAssumeRequiredAttributes() || hasAllReqAttributes(credential.getAttributes(), AUTHENTICATION_STAGE.ATTRIBUTES)) {
if (exOpt.getExcludedEndpoints()!=null && exOpt.getExcludedEndpoints().contains(aggCredential.getRemoteEntityID())) {
if (exOpt.isAssumeRequiredAttributes() || aggCredential.isHasAllAttributes()) {
queryRequired = false;
}
break;
......@@ -56,20 +63,34 @@ public class SAMLAttributeAggregationService {
}
}
this.logAttributes(credential.getAttributes(), " attribute(s) presented for credential ");
this.logAttributes(aggCredential.getAttributes(), " attribute(s) presented for credential ");
if (queryRequired) {
try {
List<Attribute> queryReturnedAttributes = attributeQuery.queryAttributes(credential, queryOptions);;
List<Attribute> queryReturnedAttributes = attributeQuery.queryAttributes(aggCredential, queryOptions);
this.logAttributes(queryReturnedAttributes, " attribute(s) resolved by attribute query ");
return new SAMLAggregatedCredential(credential, queryReturnedAttributes);
if (queryReturnedAttributes!=null && queryReturnedAttributes.size()>0) {
List<Attribute> overallAttributes = new ArrayList<Attribute>();
overallAttributes.addAll(queryReturnedAttributes);
if (aggCredential.getAttributes()!=null) {
overallAttributes.addAll(aggCredential.getAttributes());
}
aggCredential = new SAMLAggregatedCredential(aggCredential, queryReturnedAttributes, hasAllReqAttributes(overallAttributes, AUTHENTICATION_STAGE.ATTRIBUTES));
if (!aggCredential.isHasAllAttributes()) {
throw new UserCredentialsException(UserCredentialsExceptionTypes.ATTRIBUTESET_INCOMPLETE, "Incomplete set of attributes presented; terminating authentication");
}
}
} catch (UserCredentialsException e) {
logger.info(e.getMessage());
throw e;
} catch (Exception e) {
logger.error("An exception occured while attempting to permorm attribute query", e);
logger.info("An exception occured while attempting to permorm attribute query", e);
throw new UserCredentialsException(UserCredentialsExceptionTypes.ID_ATTRIBUTE_NOT_PROVIDED, "Failed to aggregate required attributes", e);
}
}
return credential;
return aggCredential;
}
private void logAttributes(List<Attribute> attributes, String message) {
......
......@@ -8,11 +8,14 @@ import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.ws.message.decoder.MessageDecodingException;
import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.xml.encryption.DecryptionException;
import org.opensaml.xml.security.SecurityException;
import org.opensaml.xml.validation.ValidationException;
import org.springframework.security.saml.SAMLCredential;
import eu.dariah.de.dariahsp.saml.attributequery.options.SAMLAttributeQueryOptions;
public interface SAMLAttributeQuery {
public List<Attribute> queryAttributes(SAMLCredential subjectCredential, SAMLAttributeQueryOptions options)
throws MetadataProviderException, MessageDecodingException, MessageEncodingException, SAMLException;
throws MetadataProviderException, MessageDecodingException, MessageEncodingException, SAMLException, SecurityException, ValidationException, DecryptionException;
}
......@@ -111,35 +111,30 @@ public class SAMLAttributeQueryImpl extends WebSSOProfileConsumerImpl implements
return SAML2_QUERY_PROFILE_URI;
}
public List<Attribute> queryAttributes(SAMLCredential subjectCredential, SAMLAttributeQueryOptions options)
@Override
public List<Attribute> queryAttributes(SAMLCredential subjectCredential, SAMLAttributeQueryOptions options) throws MessageDecodingException, MetadataProviderException, SAMLException, SecurityException, ValidationException, DecryptionException, MessageEncodingException
{
try {
logger.debug("Performing attribute query for subject with NameID [%s]", subjectCredential.getNameID().getValue());
SAMLMessageContext context = prepareAttributeQueryContext(subjectCredential, options);
AttributeQuery query = getAttributeQuery(context, subjectCredential, options);;
logger.debug("Performing attribute query for subject with NameID [%s]", subjectCredential.getNameID().getValue());
context.setOutboundMessage(query);
context.setOutboundSAMLMessage(query);
if (context.getPeerEntityEndpoint() != null) {
query.setDestination(context.getPeerEntityEndpoint().getLocation());
}
SAMLMessageContext context = prepareAttributeQueryContext(subjectCredential, options);
AttributeQuery query = getAttributeQuery(context, subjectCredential, options);;
context.setOutboundMessage(query);
context.setOutboundSAMLMessage(query);
// Generate and send query to IDP
getAttributeQueryResponse(context);
// Unwrap and process response from IDP
List <Attribute> attrs = processResponse(context, query, options);
logger.debug("SAML AttributeQuery resulted in the retrieval of {} attributes", attrs.size());
return attrs;
} catch (Exception e) {
logger.error("Exception raised white attempting to perform SAML AttributeQuery", e);
}
return null;
if (context.getPeerEntityEndpoint() != null) {
query.setDestination(context.getPeerEntityEndpoint().getLocation());
}
// Generate and send query to IDP
getAttributeQueryResponse(context);
// Unwrap and process response from IDP
List <Attribute> attrs = processResponse(context, query, options);
logger.debug("SAML AttributeQuery resulted in the retrieval of {} attributes", attrs.size());
return attrs;
}
private SAMLMessageContext prepareAttributeQueryContext(SAMLCredential credential, SAMLAttributeQueryOptions options) throws MetadataProviderException, MessageDecodingException {
......
......@@ -12,10 +12,19 @@ import org.springframework.security.saml.SAMLCredential;
public class SAMLAggregatedCredential extends SAMLCredential {
private static final long serialVersionUID = -4550065741514736227L;
private boolean hasAllAttributes;
private final List<Attribute> aggregatedAttributes;
public List<Attribute> getAggregatedAttributes() { return aggregatedAttributes; }
public boolean isHasAllAttributes() { return hasAllAttributes; }
public void setHasAllAttributes(boolean hasAllAttributes) { this.hasAllAttributes = hasAllAttributes; }
public List<Attribute> getAggregatedAttributes() { return aggregatedAttributes; }
public SAMLAggregatedCredential(NameID nameID, Assertion authenticationAssertion, String remoteEntityID, String localEntityID) {
super(nameID, authenticationAssertion, remoteEntityID, Collections.<Attribute>emptyList(), localEntityID);
this.aggregatedAttributes = null;
......@@ -40,4 +49,10 @@ public class SAMLAggregatedCredential extends SAMLCredential {
super(baseCredential.getNameID(), baseCredential.getAuthenticationAssertion(), baseCredential.getRemoteEntityID(), baseCredential.getRelayState(), baseCredential.getAttributes(), baseCredential.getLocalEntityID(), baseCredential.getAdditionalData());
this.aggregatedAttributes = aggregatedAttributes;
}
public SAMLAggregatedCredential(SAMLCredential baseCredential, List<Attribute> aggregatedAttributes, boolean hasAllAttributes) {
super(baseCredential.getNameID(), baseCredential.getAuthenticationAssertion(), baseCredential.getRemoteEntityID(), baseCredential.getRelayState(), baseCredential.getAttributes(), baseCredential.getLocalEntityID(), baseCredential.getAdditionalData());
this.aggregatedAttributes = aggregatedAttributes;
this.hasAllAttributes = hasAllAttributes;
}
}
......@@ -15,6 +15,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import eu.dariah.de.dariahsp.exceptions.UserCredentialsException;
/**
*
* @author tobias
......@@ -66,13 +68,19 @@ public class SampleExceptionController {
this.handleSAMLException((SAMLException)authEx.getCause());
}
if (authEx instanceof UserCredentialsException) {
errorMsg = authEx.getMessage();
errorPage.addObject("exception", authEx);
}
errorMsg = authEx.getMessage();
} else {
errorPage.addObject("errorMsg", errorMsg);
errorPage.addObject("exception", this.getException(httpRequest));
}
errorPage.addObject("errorMsg", errorMsg);
errorPage.addObject("exception", this.getException(httpRequest));
return errorPage;
}
......
......@@ -40,6 +40,7 @@ auth:
return: https://schereg.de.dariah.eu/schereg/saml/login/alias/schereg?disco:true
ecpEnabled: true
#allowedNameIds: EMAIL, TRANSIENT, PERSISTENT, UNSPECIFIED, X509_SUBJECT
allowedNameIds: EMAIL, PERSISTENT, X509_SUBJECT
signingKey: dfa.de.dariah.eu
encryptionKey: dfa.de.dariah.eu
tlsKey: dfa.de.dariah.eu
......@@ -47,7 +48,7 @@ auth:
enabled: true
excludedEndpoints:
urls: ["https://ldap-dariah-clone.esc.rzg.mpg.de/idp/shibboleth", "https://idp.de.dariah.eu/idp/shibboleth"]
assumeAttributesComplete: false
assumeAttributesComplete: true
queryIdp: https://ldap-dariah-clone.esc.rzg.mpg.de/idp/shibboleth
#queryIdp: https://idp.de.dariah.eu/idp/shibboleth
queryByNameID: false
......@@ -61,25 +62,33 @@ auth:
attributeGroup:
- check: AND
attributes:
- friendlyName: eduPersonPrincipalName
name: urn:oid:1.3.6.1.4.1.5923.1.1.1.6
- friendlyName: mail
name: urn:oid:0.9.2342.19200300.100.1.3
nameFormat: urn:oasis:names:tc:SAML:2.0:attrname-format:uri
- stage: AUTHENTICATION
- stage: ATTRIBUTES
required: true
attributeGroup:
- check: AND
- check: OR
attributes:
- friendlyName: eduPersonPrincipalName
name: urn:oid:1.3.6.1.4.1.5923.1.1.1.6
- friendlyName: dariahTermsOfUse
name: urn:oid:1.3.6.1.4.1.10126.1.52.4.15
nameFormat: urn:oasis:names:tc:SAML:2.0:attrname-format:uri
- friendlyName: mail
name: urn:oid:0.9.2342.19200300.100.1.3
value: Terms_of_Use_v5.pdf
- friendlyName: dariahTermsOfUse
name: urn:oid:1.3.6.1.4.1.10126.1.52.4.15
nameFormat: urn:oasis:names:tc:SAML:2.0:attrname-format:uri
value: foobar-service-agreement_version1.pdf
- stage: AUTHENTICATION
required: false
attributeGroup:
- check: OPTIONAL
attributes:
- friendlyName: eduPersonPrincipalName
name: urn:oid:1.3.6.1.4.1.5923.1.1.1.6
nameFormat: urn:oasis:names:tc:SAML:2.0:attrname-format:uri
- friendlyName: mail
name: urn:oid:0.9.2342.19200300.100.1.3
nameFormat: urn:oasis:names:tc:SAML:2.0:attrname-format:uri
- friendlyName: eduPersonEntitlement
name: urn:oid:1.3.6.1.4.1.5923.1.1.1.7
nameFormat: urn:oasis:names:tc:SAML:2.0:attrname-format:uri
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment