use of org.apache.syncope.core.logic.saml2.SAML2IdPEntity in project syncope by apache.
the class SAML2IdPLogic method importIdPs.
private List<SAML2IdPTO> importIdPs(final InputStream input) throws Exception {
List<EntityDescriptor> idpEntityDescriptors = new ArrayList<>();
Element root = OpenSAMLUtil.getParserPool().parse(new InputStreamReader(input)).getDocumentElement();
if (SAMLConstants.SAML20MD_NS.equals(root.getNamespaceURI()) && EntityDescriptor.DEFAULT_ELEMENT_LOCAL_NAME.equals(root.getLocalName())) {
idpEntityDescriptors.add((EntityDescriptor) OpenSAMLUtil.fromDom(root));
} else if (SAMLConstants.SAML20MD_NS.equals(root.getNamespaceURI()) && EntitiesDescriptor.DEFAULT_ELEMENT_LOCAL_NAME.equals(root.getLocalName())) {
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (SAMLConstants.SAML20MD_NS.equals(child.getNamespaceURI()) && EntityDescriptor.DEFAULT_ELEMENT_LOCAL_NAME.equals(child.getLocalName())) {
NodeList descendants = child.getChildNodes();
for (int j = 0; j < descendants.getLength(); j++) {
Node descendant = descendants.item(j);
if (SAMLConstants.SAML20MD_NS.equals(descendant.getNamespaceURI()) && IDPSSODescriptor.DEFAULT_ELEMENT_LOCAL_NAME.equals(descendant.getLocalName())) {
idpEntityDescriptors.add((EntityDescriptor) OpenSAMLUtil.fromDom((Element) child));
}
}
}
}
}
List<SAML2IdPTO> result = new ArrayList<>(idpEntityDescriptors.size());
for (EntityDescriptor idpEntityDescriptor : idpEntityDescriptors) {
SAML2IdPTO idpTO = new SAML2IdPTO();
idpTO.setEntityID(idpEntityDescriptor.getEntityID());
idpTO.setName(idpEntityDescriptor.getEntityID());
idpTO.setUseDeflateEncoding(false);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
saml2rw.write(new OutputStreamWriter(baos), idpEntityDescriptor, false);
idpTO.setMetadata(Base64.getEncoder().encodeToString(baos.toByteArray()));
}
ItemTO connObjectKeyItem = new ItemTO();
connObjectKeyItem.setIntAttrName("username");
connObjectKeyItem.setExtAttrName("NameID");
idpTO.setConnObjectKeyItem(connObjectKeyItem);
SAML2IdPEntity idp = cache.put(idpEntityDescriptor, idpTO);
if (idp.getSSOLocation(SAML2BindingType.POST) != null) {
idpTO.setBindingType(SAML2BindingType.POST);
} else if (idp.getSSOLocation(SAML2BindingType.REDIRECT) != null) {
idpTO.setBindingType(SAML2BindingType.REDIRECT);
} else {
throw new IllegalArgumentException("Neither POST nor REDIRECT artifacts supported by " + idp.getId());
}
result.add(idpTO);
}
return result;
}
use of org.apache.syncope.core.logic.saml2.SAML2IdPEntity in project syncope by apache.
the class SAML2SPLogic method createLogoutRequest.
@PreAuthorize("isAuthenticated() and not(hasRole('" + StandardEntitlement.ANONYMOUS + "'))")
public SAML2RequestTO createLogoutRequest(final String accessToken, final String spEntityID) {
check();
// 1. fetch the current JWT used for Syncope authentication
JwsJwtCompactConsumer consumer = new JwsJwtCompactConsumer(accessToken);
if (!consumer.verifySignatureWith(jwsSignatureVerifier)) {
throw new IllegalArgumentException("Invalid signature found in Access Token");
}
// 2. look for IdP
String idpEntityID = (String) consumer.getJwtClaims().getClaim(JWT_CLAIM_IDP_ENTITYID);
if (idpEntityID == null) {
throw new NotFoundException("No SAML 2.0 IdP information found in the access token");
}
SAML2IdPEntity idp = cache.get(idpEntityID);
if (idp == null) {
throw new NotFoundException("SAML 2.0 IdP '" + idpEntityID + "'");
}
if (idp.getSLOLocation(idp.getBindingType()) == null) {
throw new IllegalArgumentException("No SingleLogoutService available for " + idp.getId());
}
// 3. create LogoutRequest
LogoutRequest logoutRequest = new LogoutRequestBuilder().buildObject();
logoutRequest.setID("_" + UUID_GENERATOR.generate().toString());
logoutRequest.setDestination(idp.getSLOLocation(idp.getBindingType()).getLocation());
DateTime now = new DateTime();
logoutRequest.setIssueInstant(now);
logoutRequest.setNotOnOrAfter(now.plusMinutes(5));
Issuer issuer = new IssuerBuilder().buildObject();
issuer.setValue(spEntityID);
logoutRequest.setIssuer(issuer);
NameID nameID = new NameIDBuilder().buildObject();
nameID.setFormat((String) consumer.getJwtClaims().getClaim(JWT_CLAIM_NAMEID_FORMAT));
nameID.setValue((String) consumer.getJwtClaims().getClaim(JWT_CLAIM_NAMEID_VALUE));
logoutRequest.setNameID(nameID);
SessionIndex sessionIndex = new SessionIndexBuilder().buildObject();
sessionIndex.setSessionIndex((String) consumer.getJwtClaims().getClaim(JWT_CLAIM_SESSIONINDEX));
logoutRequest.getSessionIndexes().add(sessionIndex);
SAML2RequestTO requestTO = new SAML2RequestTO();
requestTO.setIdpServiceAddress(logoutRequest.getDestination());
requestTO.setBindingType(idp.getBindingType());
try {
// 3. generate relay state as JWT
Map<String, Object> claims = new HashMap<>();
claims.put(JWT_CLAIM_IDP_DEFLATE, idp.getBindingType() == SAML2BindingType.REDIRECT ? true : idp.isUseDeflateEncoding());
Triple<String, String, Date> relayState = accessTokenDataBinder.generateJWT(logoutRequest.getID(), JWT_RELAY_STATE_DURATION, claims);
requestTO.setRelayState(relayState.getMiddle());
// 4. sign and encode AuthnRequest
switch(idp.getBindingType()) {
case REDIRECT:
requestTO.setContent(saml2rw.encode(logoutRequest, true));
requestTO.setSignAlg(saml2rw.getSigAlgo());
requestTO.setSignature(saml2rw.sign(requestTO.getContent(), requestTO.getRelayState()));
break;
case POST:
default:
saml2rw.sign(logoutRequest);
requestTO.setContent(saml2rw.encode(logoutRequest, idp.isUseDeflateEncoding()));
}
} catch (Exception e) {
LOG.error("While generating LogoutRequest", e);
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
sce.getElements().add(e.getMessage());
throw sce;
}
return requestTO;
}
use of org.apache.syncope.core.logic.saml2.SAML2IdPEntity in project syncope by apache.
the class SAML2SPLogic method getIdP.
private SAML2IdPEntity getIdP(final String entityID) {
SAML2IdPEntity idp = null;
SAML2IdP saml2IdP = saml2IdPDAO.findByEntityID(entityID);
if (saml2IdP != null) {
try {
idp = cache.put(saml2IdP);
} catch (Exception e) {
LOG.error("Could not build SAML 2.0 IdP with key ", entityID, e);
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
sce.getElements().add(e.getMessage());
throw sce;
}
}
if (idp == null) {
throw new NotFoundException("SAML 2.0 IdP '" + entityID + "'");
}
return idp;
}
use of org.apache.syncope.core.logic.saml2.SAML2IdPEntity in project syncope by apache.
the class SAML2SPLogic method createLoginRequest.
@PreAuthorize("hasRole('" + StandardEntitlement.ANONYMOUS + "')")
public SAML2RequestTO createLoginRequest(final String spEntityID, final String idpEntityID) {
check();
// 1. look for IdP
SAML2IdPEntity idp = StringUtils.isBlank(idpEntityID) ? cache.getFirst() : cache.get(idpEntityID);
if (idp == null) {
if (StringUtils.isBlank(idpEntityID)) {
List<SAML2IdP> all = saml2IdPDAO.findAll();
if (!all.isEmpty()) {
idp = getIdP(all.get(0).getKey());
}
} else {
idp = getIdP(idpEntityID);
}
}
if (idp == null) {
throw new NotFoundException(StringUtils.isBlank(idpEntityID) ? "Any SAML 2.0 IdP" : "SAML 2.0 IdP '" + idpEntityID + "'");
}
if (idp.getSSOLocation(idp.getBindingType()) == null) {
throw new IllegalArgumentException("No SingleSignOnService available for " + idp.getId());
}
// 2. create AuthnRequest
Issuer issuer = new IssuerBuilder().buildObject();
issuer.setValue(spEntityID);
NameIDPolicy nameIDPolicy = new NameIDPolicyBuilder().buildObject();
if (idp.supportsNameIDFormat(NameIDType.TRANSIENT)) {
nameIDPolicy.setFormat(NameIDType.TRANSIENT);
} else if (idp.supportsNameIDFormat(NameIDType.PERSISTENT)) {
nameIDPolicy.setFormat(NameIDType.PERSISTENT);
} else {
throw new IllegalArgumentException("Could not find supported NameIDFormat for IdP " + idpEntityID);
}
nameIDPolicy.setAllowCreate(true);
nameIDPolicy.setSPNameQualifier(spEntityID);
AuthnContextClassRef authnContextClassRef = new AuthnContextClassRefBuilder().buildObject();
authnContextClassRef.setAuthnContextClassRef(AuthnContext.PPT_AUTHN_CTX);
RequestedAuthnContext requestedAuthnContext = new RequestedAuthnContextBuilder().buildObject();
requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT);
requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef);
AuthnRequest authnRequest = new AuthnRequestBuilder().buildObject();
authnRequest.setID("_" + UUID_GENERATOR.generate().toString());
authnRequest.setForceAuthn(false);
authnRequest.setIsPassive(false);
authnRequest.setVersion(SAMLVersion.VERSION_20);
authnRequest.setProtocolBinding(idp.getBindingType().getUri());
authnRequest.setIssueInstant(new DateTime());
authnRequest.setIssuer(issuer);
authnRequest.setNameIDPolicy(nameIDPolicy);
authnRequest.setRequestedAuthnContext(requestedAuthnContext);
authnRequest.setDestination(idp.getSSOLocation(idp.getBindingType()).getLocation());
SAML2RequestTO requestTO = new SAML2RequestTO();
requestTO.setIdpServiceAddress(authnRequest.getDestination());
requestTO.setBindingType(idp.getBindingType());
try {
// 3. generate relay state as JWT
Map<String, Object> claims = new HashMap<>();
claims.put(JWT_CLAIM_IDP_DEFLATE, idp.isUseDeflateEncoding());
Triple<String, String, Date> relayState = accessTokenDataBinder.generateJWT(authnRequest.getID(), JWT_RELAY_STATE_DURATION, claims);
// 4. sign and encode AuthnRequest
switch(idp.getBindingType()) {
case REDIRECT:
requestTO.setRelayState(URLEncoder.encode(relayState.getMiddle(), StandardCharsets.UTF_8.name()));
requestTO.setContent(URLEncoder.encode(saml2rw.encode(authnRequest, true), StandardCharsets.UTF_8.name()));
requestTO.setSignAlg(URLEncoder.encode(saml2rw.getSigAlgo(), StandardCharsets.UTF_8.name()));
requestTO.setSignature(URLEncoder.encode(saml2rw.sign(requestTO.getContent(), requestTO.getRelayState()), StandardCharsets.UTF_8.name()));
break;
case POST:
default:
requestTO.setRelayState(relayState.getMiddle());
saml2rw.sign(authnRequest);
requestTO.setContent(saml2rw.encode(authnRequest, idp.isUseDeflateEncoding()));
}
} catch (Exception e) {
LOG.error("While generating AuthnRequest", e);
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
sce.getElements().add(e.getMessage());
throw sce;
}
return requestTO;
}
use of org.apache.syncope.core.logic.saml2.SAML2IdPEntity in project syncope by apache.
the class SAML2IdPLogic method complete.
private SAML2IdPTO complete(final SAML2IdP idp, final SAML2IdPTO idpTO) {
SAML2IdPEntity idpEntity = cache.get(idpTO.getEntityID());
if (idpEntity == null) {
try {
idpEntity = cache.put(idp);
} catch (Exception e) {
LOG.error("Could not build SAML 2.0 IdP with key ", idp.getEntityID(), e);
}
}
idpTO.setLogoutSupported(idpEntity == null ? false : idpEntity.getSLOLocation(SAML2BindingType.POST) != null || idpEntity.getSLOLocation(SAML2BindingType.REDIRECT) != null);
return idpTO;
}
Aggregations