use of org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer in project cxf by apache.
the class JWTProviderLifetimeTest method testJWTExceededConfiguredMaxLifetimeButUpdated.
/**
* Issue JWT token with a with a lifetime
* which exceeds configured maximum lifetime
* Lifetime reduced to maximum lifetime
*/
@org.junit.Test
public void testJWTExceededConfiguredMaxLifetimeButUpdated() throws Exception {
// 30 minutes
long maxLifetime = 30 * 60L;
JWTTokenProvider tokenProvider = new JWTTokenProvider();
DefaultJWTClaimsProvider claimsProvider = new DefaultJWTClaimsProvider();
claimsProvider.setMaxLifetime(maxLifetime);
claimsProvider.setFailLifetimeExceedance(false);
claimsProvider.setAcceptClientLifetime(true);
tokenProvider.setJwtClaimsProvider(claimsProvider);
TokenProviderParameters providerParameters = createProviderParameters(JWTTokenProvider.JWT_TOKEN_TYPE);
// Set expected lifetime to 35 minutes
Instant creationTime = Instant.now();
long requestedLifetime = 35 * 60L;
Instant expirationTime = creationTime.plusSeconds(requestedLifetime);
Lifetime lifetime = new Lifetime();
lifetime.setCreated(creationTime.atZone(ZoneOffset.UTC).format(DateUtil.getDateTimeFormatter(true)));
lifetime.setExpires(expirationTime.atZone(ZoneOffset.UTC).format(DateUtil.getDateTimeFormatter(true)));
providerParameters.getTokenRequirements().setLifetime(lifetime);
TokenProviderResponse providerResponse = tokenProvider.createToken(providerParameters);
assertNotNull(providerResponse);
assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
long duration = Duration.between(providerResponse.getCreated(), providerResponse.getExpires()).getSeconds();
assertEquals(maxLifetime, duration);
String token = (String) providerResponse.getToken();
assertNotNull(token);
JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(token);
JwtToken jwt = jwtConsumer.getJwtToken();
assertEquals(jwt.getClaim(JwtConstants.CLAIM_ISSUED_AT), providerResponse.getCreated().getEpochSecond());
}
use of org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer in project cxf by apache.
the class STSRESTTest method validateJWTToken.
private static JwtToken validateJWTToken(String token) throws Exception {
assertNotNull(token);
JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(token);
JwtToken jwt = jwtConsumer.getJwtToken();
// Validate claims
assertEquals("DoubleItSTSIssuer", jwt.getClaims().getIssuer());
assertNotNull(jwt.getClaims().getExpiryTime());
assertNotNull(jwt.getClaims().getIssuedAt());
CryptoType alias = new CryptoType(CryptoType.TYPE.ALIAS);
alias.setAlias("mystskey");
X509Certificate stsCertificate = serviceCrypto.getX509Certificates(alias)[0];
assertTrue(jwtConsumer.verifySignatureWith(stsCertificate, SignatureAlgorithm.RS256));
return jwt;
}
use of org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer in project syncope by apache.
the class SAML2SPLogic method validateLoginResponse.
@PreAuthorize("hasRole('" + StandardEntitlement.ANONYMOUS + "')")
public SAML2LoginResponseTO validateLoginResponse(final SAML2ReceivedResponseTO response) {
check();
// 1. first checks for the provided relay state
if (response.getRelayState() == null) {
throw new IllegalArgumentException("No Relay State was provided");
}
Boolean useDeflateEncoding = false;
String requestId = null;
if (!IDP_INITIATED_RELAY_STATE.equals(response.getRelayState())) {
JwsJwtCompactConsumer relayState = new JwsJwtCompactConsumer(response.getRelayState());
if (!relayState.verifySignatureWith(jwsSignatureVerifier)) {
throw new IllegalArgumentException("Invalid signature found in Relay State");
}
useDeflateEncoding = Boolean.valueOf(relayState.getJwtClaims().getClaim(JWT_CLAIM_IDP_DEFLATE).toString());
requestId = relayState.getJwtClaims().getSubject();
Long expiryTime = relayState.getJwtClaims().getExpiryTime();
if (expiryTime == null || (expiryTime * 1000L) < new Date().getTime()) {
throw new IllegalArgumentException("Relay State is expired");
}
}
// 2. parse the provided SAML response
if (response.getSamlResponse() == null) {
throw new IllegalArgumentException("No SAML Response was provided");
}
Response samlResponse;
try {
XMLObject responseObject = saml2rw.read(useDeflateEncoding, response.getSamlResponse());
if (!(responseObject instanceof Response)) {
throw new IllegalArgumentException("Expected " + Response.class.getName() + ", got " + responseObject.getClass().getName());
}
samlResponse = (Response) responseObject;
} catch (Exception e) {
LOG.error("While parsing AuthnResponse", e);
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
sce.getElements().add(e.getMessage());
throw sce;
}
// 3. validate the SAML response and, if needed, decrypt the provided assertion(s)
if (samlResponse.getIssuer() == null || samlResponse.getIssuer().getValue() == null) {
throw new IllegalArgumentException("The SAML Response must contain an Issuer");
}
final SAML2IdPEntity idp = getIdP(samlResponse.getIssuer().getValue());
if (idp.getConnObjectKeyItem() == null) {
throw new IllegalArgumentException("No mapping provided for SAML 2.0 IdP '" + idp.getId() + "'");
}
if (IDP_INITIATED_RELAY_STATE.equals(response.getRelayState()) && !idp.isSupportUnsolicited()) {
throw new IllegalArgumentException("An unsolicited request is not allowed for idp: " + idp.getId());
}
SSOValidatorResponse validatorResponse = null;
try {
validatorResponse = saml2rw.validate(samlResponse, idp, getAssertionConsumerURL(response.getSpEntityID(), response.getUrlContext()), requestId, response.getSpEntityID());
} catch (Exception e) {
LOG.error("While validating AuthnResponse", e);
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
sce.getElements().add(e.getMessage());
throw sce;
}
// 4. prepare the result: find matching user (if any) and return the received attributes
final SAML2LoginResponseTO responseTO = new SAML2LoginResponseTO();
responseTO.setIdp(idp.getId());
responseTO.setSloSupported(idp.getSLOLocation(idp.getBindingType()) != null);
Assertion assertion = validatorResponse.getOpensamlAssertion();
NameID nameID = assertion.getSubject().getNameID();
if (nameID == null) {
throw new IllegalArgumentException("NameID not found");
}
String keyValue = null;
if (StringUtils.isNotBlank(nameID.getValue()) && idp.getConnObjectKeyItem().getExtAttrName().equals("NameID")) {
keyValue = nameID.getValue();
}
if (assertion.getConditions().getNotOnOrAfter() != null) {
responseTO.setNotOnOrAfter(assertion.getConditions().getNotOnOrAfter().toDate());
}
assertion.getAuthnStatements().forEach(authnStmt -> {
responseTO.setSessionIndex(authnStmt.getSessionIndex());
responseTO.setAuthInstant(authnStmt.getAuthnInstant().toDate());
if (authnStmt.getSessionNotOnOrAfter() != null) {
responseTO.setNotOnOrAfter(authnStmt.getSessionNotOnOrAfter().toDate());
}
});
for (AttributeStatement attrStmt : assertion.getAttributeStatements()) {
for (Attribute attr : attrStmt.getAttributes()) {
if (!attr.getAttributeValues().isEmpty()) {
String attrName = attr.getFriendlyName() == null ? attr.getName() : attr.getFriendlyName();
if (attrName.equals(idp.getConnObjectKeyItem().getExtAttrName())) {
if (attr.getAttributeValues().get(0) instanceof XSString) {
keyValue = ((XSString) attr.getAttributeValues().get(0)).getValue();
} else if (attr.getAttributeValues().get(0) instanceof XSAny) {
keyValue = ((XSAny) attr.getAttributeValues().get(0)).getTextContent();
}
}
AttrTO attrTO = new AttrTO();
attrTO.setSchema(attrName);
attr.getAttributeValues().stream().filter(value -> value.getDOM() != null).forEachOrdered(value -> {
attrTO.getValues().add(value.getDOM().getTextContent());
});
responseTO.getAttrs().add(attrTO);
}
}
}
final List<String> matchingUsers = keyValue == null ? Collections.<String>emptyList() : userManager.findMatchingUser(keyValue, idp.getKey());
LOG.debug("Found {} matching users for {}", matchingUsers.size(), keyValue);
String username;
if (matchingUsers.isEmpty()) {
if (idp.isCreateUnmatching()) {
LOG.debug("No user matching {}, about to create", keyValue);
username = AuthContextUtils.execWithAuthContext(AuthContextUtils.getDomain(), () -> userManager.create(idp, responseTO, nameID.getValue()));
} else if (idp.isSelfRegUnmatching()) {
responseTO.setNameID(nameID.getValue());
UserTO userTO = new UserTO();
userManager.fill(idp.getKey(), responseTO, userTO);
responseTO.getAttrs().clear();
responseTO.getAttrs().addAll(userTO.getPlainAttrs());
responseTO.getAttrs().addAll(userTO.getVirAttrs());
if (StringUtils.isNotBlank(userTO.getUsername())) {
responseTO.setUsername(userTO.getUsername());
}
responseTO.setSelfReg(true);
return responseTO;
} else {
throw new NotFoundException("User matching the provided value " + keyValue);
}
} else if (matchingUsers.size() > 1) {
throw new IllegalArgumentException("Several users match the provided value " + keyValue);
} else {
if (idp.isUpdateMatching()) {
LOG.debug("About to update {} for {}", matchingUsers.get(0), keyValue);
username = AuthContextUtils.execWithAuthContext(AuthContextUtils.getDomain(), () -> userManager.update(matchingUsers.get(0), idp, responseTO));
} else {
username = matchingUsers.get(0);
}
}
responseTO.setUsername(username);
responseTO.setNameID(nameID.getValue());
// 5. generate JWT for further access
Map<String, Object> claims = new HashMap<>();
claims.put(JWT_CLAIM_IDP_ENTITYID, idp.getId());
claims.put(JWT_CLAIM_NAMEID_FORMAT, nameID.getFormat());
claims.put(JWT_CLAIM_NAMEID_VALUE, nameID.getValue());
claims.put(JWT_CLAIM_SESSIONINDEX, responseTO.getSessionIndex());
byte[] authorities = null;
try {
authorities = ENCRYPTOR.encode(POJOHelper.serialize(authDataAccessor.getAuthorities(responseTO.getUsername())), CipherAlgorithm.AES).getBytes();
} catch (Exception e) {
LOG.error("Could not fetch authorities", e);
}
Pair<String, Date> accessTokenInfo = accessTokenDataBinder.create(responseTO.getUsername(), claims, authorities, true);
responseTO.setAccessToken(accessTokenInfo.getLeft());
responseTO.setAccessTokenExpiryTime(accessTokenInfo.getRight());
return responseTO;
}
use of org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer in project syncope by apache.
the class SAML2SPLogic method validateLogoutResponse.
@PreAuthorize("isAuthenticated() and not(hasRole('" + StandardEntitlement.ANONYMOUS + "'))")
public void validateLogoutResponse(final String accessToken, final SAML2ReceivedResponseTO response) {
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. extract raw SAML response and relay state
JwsJwtCompactConsumer relayState = null;
Boolean useDeflateEncoding = false;
if (StringUtils.isNotBlank(response.getRelayState())) {
// first checks for the provided relay state, if available
relayState = new JwsJwtCompactConsumer(response.getRelayState());
if (!relayState.verifySignatureWith(jwsSignatureVerifier)) {
throw new IllegalArgumentException("Invalid signature found in Relay State");
}
Long expiryTime = relayState.getJwtClaims().getExpiryTime();
if (expiryTime == null || (expiryTime * 1000L) < new Date().getTime()) {
throw new IllegalArgumentException("Relay State is expired");
}
useDeflateEncoding = Boolean.valueOf(relayState.getJwtClaims().getClaim(JWT_CLAIM_IDP_DEFLATE).toString());
}
// 3. parse the provided SAML response
LogoutResponse logoutResponse;
try {
XMLObject responseObject = saml2rw.read(useDeflateEncoding, response.getSamlResponse());
if (!(responseObject instanceof LogoutResponse)) {
throw new IllegalArgumentException("Expected " + LogoutResponse.class.getName() + ", got " + responseObject.getClass().getName());
}
logoutResponse = (LogoutResponse) responseObject;
} catch (Exception e) {
LOG.error("While parsing LogoutResponse", e);
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
sce.getElements().add(e.getMessage());
throw sce;
}
// 4. if relay state was available, check the SAML Reponse's InResponseTo
if (relayState != null && !relayState.getJwtClaims().getSubject().equals(logoutResponse.getInResponseTo())) {
throw new IllegalArgumentException("Unmatching request ID: " + logoutResponse.getInResponseTo());
}
// 5. finally check for the logout status
if (StatusCode.SUCCESS.equals(logoutResponse.getStatus().getStatusCode().getValue())) {
accessTokenDAO.delete(consumer.getJwtClaims().getTokenId());
} else {
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
if (logoutResponse.getStatus().getStatusMessage() == null) {
sce.getElements().add(logoutResponse.getStatus().getStatusCode().getValue());
} else {
sce.getElements().add(logoutResponse.getStatus().getStatusMessage().getMessage());
}
throw sce;
}
}
use of org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer in project syncope by apache.
the class SAML2ITCase method unsignedAssertionInLoginResponse.
@Test
public void unsignedAssertionInLoginResponse() throws Exception {
assumeTrue(SAML2SPDetector.isSAML2SPAvailable());
// Get a valid login request for the Fediz realm
SAML2SPService saml2Service = anonymous.getService(SAML2SPService.class);
SAML2RequestTO loginRequest = saml2Service.createLoginRequest(ADDRESS, "urn:org:apache:cxf:fediz:idp:realm-A");
assertNotNull(loginRequest);
SAML2ReceivedResponseTO response = new SAML2ReceivedResponseTO();
response.setSpEntityID("http://recipient.apache.org/");
response.setUrlContext("saml2sp");
response.setRelayState(loginRequest.getRelayState());
// Create a SAML Response using WSS4J
JwsJwtCompactConsumer relayState = new JwsJwtCompactConsumer(response.getRelayState());
String inResponseTo = relayState.getJwtClaims().getSubject();
org.opensaml.saml.saml2.core.Response samlResponse = createResponse(inResponseTo, false, SAML2Constants.CONF_SENDER_VOUCHES, "urn:org:apache:cxf:fediz:idp:realm-A");
Document doc = DOMUtils.newDocument();
Element responseElement = OpenSAMLUtil.toDom(samlResponse, doc);
String responseStr = DOM2Writer.nodeToString(responseElement);
// Validate the SAML Response
response.setSamlResponse(Base64.getEncoder().encodeToString(responseStr.getBytes()));
try {
saml2Service.validateLoginResponse(response);
fail("Failure expected on an unsigned Assertion");
} catch (SyncopeClientException e) {
assertNotNull(e);
}
}
Aggregations