use of org.keycloak.dom.saml.v2.protocol.ResponseType in project keycloak by keycloak.
the class SAMLResponseParser method instantiateElement.
@Override
protected ResponseType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
SAMLParserUtil.validateAttributeValue(element, SAMLProtocolQNames.ATTR_VERSION, VERSION_2_0);
String id = StaxParserUtil.getRequiredAttributeValue(element, SAMLProtocolQNames.ATTR_ID);
XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getRequiredAttributeValue(element, SAMLProtocolQNames.ATTR_ISSUE_INSTANT));
ResponseType res = new ResponseType(id, issueInstant);
// Let us set the attributes
super.parseBaseAttributes(element, res);
return res;
}
use of org.keycloak.dom.saml.v2.protocol.ResponseType in project keycloak by keycloak.
the class SAMLResponseParser method processSubElement.
@Override
protected void processSubElement(XMLEventReader xmlEventReader, ResponseType target, SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
switch(element) {
case ISSUER:
target.setIssuer(SAMLParserUtil.parseNameIDType(xmlEventReader));
break;
case SIGNATURE:
Element sig = StaxParserUtil.getDOMElement(xmlEventReader);
target.setSignature(sig);
break;
case ASSERTION:
target.addAssertion(new RTChoiceType(SAMLAssertionParser.getInstance().parse(xmlEventReader)));
break;
case EXTENSIONS:
target.setExtensions(SAMLExtensionsParser.getInstance().parse(xmlEventReader));
break;
case STATUS:
target.setStatus(SAMLStatusParser.getInstance().parse(xmlEventReader));
break;
case ENCRYPTED_ASSERTION:
target.addAssertion(new RTChoiceType(SAMLEncryptedAssertionParser.getInstance().parse(xmlEventReader)));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
use of org.keycloak.dom.saml.v2.protocol.ResponseType in project keycloak by keycloak.
the class SamlProtocol method authenticated.
@Override
public Response authenticated(AuthenticationSessionModel authSession, UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession();
ClientModel client = clientSession.getClient();
SamlClient samlClient = new SamlClient(client);
String requestID = authSession.getClientNote(SAML_REQUEST_ID);
String relayState = authSession.getClientNote(GeneralConstants.RELAY_STATE);
String redirectUri = authSession.getRedirectUri();
String responseIssuer = getResponseIssuer(realm);
String nameIdFormat = getNameIdFormat(samlClient, authSession);
int assertionLifespan = samlClient.getAssertionLifespan();
SAML2LoginResponseBuilder builder = new SAML2LoginResponseBuilder();
builder.requestID(requestID).destination(redirectUri).issuer(responseIssuer).assertionExpiration(assertionLifespan <= 0 ? realm.getAccessCodeLifespan() : assertionLifespan).subjectExpiration(assertionLifespan <= 0 ? realm.getAccessTokenLifespan() : assertionLifespan).sessionExpiration(realm.getSsoSessionMaxLifespan()).requestIssuer(clientSession.getClient().getClientId()).authMethod(JBossSAMLURIConstants.AC_UNSPECIFIED.get());
String sessionIndex = SamlSessionUtils.getSessionIndex(clientSession);
builder.sessionIndex(sessionIndex);
if (!samlClient.includeAuthnStatement()) {
builder.disableAuthnStatement(true);
}
builder.includeOneTimeUseCondition(samlClient.includeOneTimeUseCondition());
List<ProtocolMapperProcessor<SAMLAttributeStatementMapper>> attributeStatementMappers = new LinkedList<>();
List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> loginResponseMappers = new LinkedList<>();
AtomicReference<ProtocolMapperProcessor<SAMLRoleListMapper>> roleListMapper = new AtomicReference<>(null);
List<ProtocolMapperProcessor<SAMLNameIdMapper>> samlNameIdMappers = new LinkedList<>();
ProtocolMapperUtils.getSortedProtocolMappers(session, clientSessionCtx).forEach(entry -> {
ProtocolMapperModel mapping = entry.getKey();
ProtocolMapper mapper = entry.getValue();
if (mapper instanceof SAMLAttributeStatementMapper) {
attributeStatementMappers.add(new ProtocolMapperProcessor<>((SAMLAttributeStatementMapper) mapper, mapping));
}
if (mapper instanceof SAMLLoginResponseMapper) {
loginResponseMappers.add(new ProtocolMapperProcessor<>((SAMLLoginResponseMapper) mapper, mapping));
}
if (mapper instanceof SAMLRoleListMapper) {
roleListMapper.set(new ProtocolMapperProcessor<>((SAMLRoleListMapper) mapper, mapping));
}
if (mapper instanceof SAMLNameIdMapper) {
samlNameIdMappers.add(new ProtocolMapperProcessor<>((SAMLNameIdMapper) mapper, mapping));
}
});
Document samlDocument = null;
ResponseType samlModel = null;
KeyManager keyManager = session.keys();
KeyManager.ActiveRsaKey keys = keyManager.getActiveRsaKey(realm);
boolean postBinding = isPostBinding(authSession);
String keyName = samlClient.getXmlSigKeyInfoKeyNameTransformer().getKeyName(keys.getKid(), keys.getCertificate());
String nameId = getSAMLNameId(samlNameIdMappers, nameIdFormat, session, userSession, clientSession);
if (nameId == null) {
return samlErrorMessage(null, samlClient, isPostBinding(authSession), redirectUri, JBossSAMLURIConstants.STATUS_INVALID_NAMEIDPOLICY, relayState);
}
builder.nameIdentifier(nameIdFormat, nameId);
// save NAME_ID and format in clientSession as they may be persistent or
// transient or email and not username
// we'll need to send this back on a logout
clientSession.setNote(SAML_NAME_ID, nameId);
clientSession.setNote(SAML_NAME_ID_FORMAT, nameIdFormat);
try {
if ((!postBinding) && samlClient.requiresRealmSignature() && samlClient.addExtensionsElementWithKeyInfo()) {
builder.addExtension(new KeycloakKeySamlExtensionGenerator(keyName));
}
samlModel = builder.buildModel();
final AttributeStatementType attributeStatement = populateAttributeStatements(attributeStatementMappers, session, userSession, clientSession);
populateRoles(roleListMapper.get(), session, userSession, clientSessionCtx, attributeStatement);
// SAML Spec 2.7.3 AttributeStatement must contain one or more Attribute or EncryptedAttribute
if (attributeStatement.getAttributes().size() > 0) {
AssertionType assertion = samlModel.getAssertions().get(0).getAssertion();
assertion.addStatement(attributeStatement);
}
samlModel = transformLoginResponse(loginResponseMappers, samlModel, session, userSession, clientSessionCtx);
} catch (Exception e) {
logger.error("failed", e);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
}
JaxrsSAML2BindingBuilder bindingBuilder = new JaxrsSAML2BindingBuilder(session);
bindingBuilder.relayState(relayState);
if ("true".equals(clientSession.getNote(JBossSAMLURIConstants.SAML_HTTP_ARTIFACT_BINDING.get()))) {
try {
return buildArtifactAuthenticatedResponse(clientSession, redirectUri, samlModel, bindingBuilder);
} catch (Exception e) {
logger.error("failed", e);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
}
}
if (samlClient.requiresRealmSignature() || samlClient.requiresAssertionSignature()) {
String canonicalization = samlClient.getCanonicalizationMethod();
if (canonicalization != null) {
bindingBuilder.canonicalizationMethod(canonicalization);
}
bindingBuilder.signatureAlgorithm(samlClient.getSignatureAlgorithm()).signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate());
if (samlClient.requiresRealmSignature())
bindingBuilder.signDocument();
if (samlClient.requiresAssertionSignature())
bindingBuilder.signAssertions();
}
if (samlClient.requiresEncryption()) {
PublicKey publicKey = null;
try {
publicKey = SamlProtocolUtils.getEncryptionKey(client);
} catch (Exception e) {
logger.error("failed", e);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
}
bindingBuilder.encrypt(publicKey);
}
try {
samlDocument = builder.buildDocument(samlModel);
return buildAuthenticatedResponse(clientSession, redirectUri, samlDocument, bindingBuilder);
} catch (Exception e) {
logger.error("failed", e);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
}
}
use of org.keycloak.dom.saml.v2.protocol.ResponseType in project keycloak by keycloak.
the class KcSamlIdPInitiatedSsoTest method testProviderTransientIdpInitiatedLogin.
@Test
public void testProviderTransientIdpInitiatedLogin() throws Exception {
IdentityProviderResource idp = adminClient.realm(REALM_CONS_NAME).identityProviders().get("saml-leaf");
IdentityProviderRepresentation rep = idp.toRepresentation();
rep.getConfig().put(SAMLIdentityProviderConfig.NAME_ID_POLICY_FORMAT, JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get());
rep.getConfig().put(SAMLIdentityProviderConfig.PRINCIPAL_TYPE, SamlPrincipalType.ATTRIBUTE.name());
rep.getConfig().put(SAMLIdentityProviderConfig.PRINCIPAL_ATTRIBUTE, X500SAMLProfileConstants.UID.get());
idp.update(rep);
SAMLDocumentHolder samlResponse = new SamlClientBuilder().navigateTo(getSamlIdpInitiatedUrl(REALM_PROV_NAME, "samlbroker")).login().user(PROVIDER_REALM_USER_NAME, PROVIDER_REALM_USER_PASSWORD).build().processSamlResponse(Binding.POST).transformObject(ob -> {
assertThat(ob, Matchers.isSamlResponse(JBossSAMLURIConstants.STATUS_SUCCESS));
ResponseType resp = (ResponseType) ob;
assertThat(resp.getDestination(), is(getSamlBrokerIdpInitiatedUrl(REALM_CONS_NAME, "sales")));
assertAudience(resp, getSamlBrokerIdpInitiatedUrl(REALM_CONS_NAME, "sales"));
NameIDType nameId = new NameIDType();
nameId.setFormat(URI.create(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get()));
nameId.setValue("subjectId1");
resp.getAssertions().get(0).getAssertion().getSubject().getSubType().addBaseID(nameId);
Set<StatementAbstractType> statements = resp.getAssertions().get(0).getAssertion().getStatements();
AttributeStatementType attributeType = (AttributeStatementType) statements.stream().filter(statement -> statement instanceof AttributeStatementType).findFirst().orElse(new AttributeStatementType());
AttributeType attr = new AttributeType(X500SAMLProfileConstants.UID.get());
attr.addAttributeValue(PROVIDER_REALM_USER_NAME);
attributeType.addAttribute(new AttributeStatementType.ASTChoiceType(attr));
resp.getAssertions().get(0).getAssertion().addStatement(attributeType);
return ob;
}).build().navigateTo(getSamlIdpInitiatedUrl(REALM_PROV_NAME, "samlbroker-2")).login().sso(true).build().processSamlResponse(Binding.POST).transformObject(ob -> {
assertThat(ob, Matchers.isSamlResponse(JBossSAMLURIConstants.STATUS_SUCCESS));
ResponseType resp = (ResponseType) ob;
assertThat(resp.getDestination(), is(getSamlBrokerIdpInitiatedUrl(REALM_CONS_NAME, "sales2")));
assertAudience(resp, getSamlBrokerIdpInitiatedUrl(REALM_CONS_NAME, "sales2"));
NameIDType nameId = new NameIDType();
nameId.setFormat(URI.create(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get()));
nameId.setValue("subjectId2");
resp.getAssertions().get(0).getAssertion().getSubject().getSubType().addBaseID(nameId);
Set<StatementAbstractType> statements = resp.getAssertions().get(0).getAssertion().getStatements();
AttributeStatementType attributeType = (AttributeStatementType) statements.stream().filter(statement -> statement instanceof AttributeStatementType).findFirst().orElse(new AttributeStatementType());
AttributeType attr = new AttributeType(X500SAMLProfileConstants.UID.get());
attr.addAttributeValue(PROVIDER_REALM_USER_NAME);
attributeType.addAttribute(new AttributeStatementType.ASTChoiceType(attr));
resp.getAssertions().get(0).getAssertion().addStatement(attributeType);
return ob;
}).build().updateProfile().username(CONSUMER_CHOSEN_USERNAME).email("test@localhost").firstName("Firstname").lastName("Lastname").build().followOneRedirect().getSamlResponse(Binding.POST);
assertThat(samlResponse.getSamlObject(), Matchers.isSamlResponse(JBossSAMLURIConstants.STATUS_SUCCESS));
ResponseType resp = (ResponseType) samlResponse.getSamlObject();
assertThat(resp.getDestination(), is(urlRealmConsumer + "/app/auth2/saml"));
assertAudience(resp, urlRealmConsumer + "/app/auth2");
UsersResource users = adminClient.realm(REALM_CONS_NAME).users();
List<UserRepresentation> userList = users.search(CONSUMER_CHOSEN_USERNAME);
assertEquals(1, userList.size());
String id = userList.get(0).getId();
FederatedIdentityRepresentation fed = users.get(id).getFederatedIdentity().get(0);
assertThat(fed.getUserId(), is(PROVIDER_REALM_USER_NAME));
assertThat(fed.getUserName(), is(PROVIDER_REALM_USER_NAME));
// check that no user with sent subject-id was sent
userList = users.search("subjectId1");
assertTrue(userList.isEmpty());
userList = users.search("subjectId2");
assertTrue(userList.isEmpty());
}
use of org.keycloak.dom.saml.v2.protocol.ResponseType in project keycloak by keycloak.
the class KcSamlIdPInitiatedSsoTest method assertAudience.
private void assertAudience(ResponseType resp, String expectedAudience) throws Exception {
AssertionType a = AssertionUtil.getAssertion(null, resp, null);
assertThat(a, notNullValue());
assertThat(a.getConditions(), notNullValue());
assertThat(a.getConditions().getConditions(), notNullValue());
assertThat(a.getConditions().getConditions(), hasSize(greaterThan(0)));
assertThat(a.getConditions().getConditions().get(0), instanceOf(AudienceRestrictionType.class));
AudienceRestrictionType ar = (AudienceRestrictionType) a.getConditions().getConditions().get(0);
assertThat(ar.getAudience(), contains(URI.create(expectedAudience)));
}
Aggregations