diff --git a/.gitignore b/.gitignore index 8253d04..286ea18 100644 --- a/.gitignore +++ b/.gitignore @@ -167,3 +167,10 @@ buildNumber.properties .classpath # End of https://www.toptal.com/developers/gitignore/api/maven,intellij+all,eclipse + +# E2E test credentials +src/test/e2e/frontend/.env +src/test/e2e/frontend/node_modules/ + +# Claude Code +.claude/ diff --git a/pom.xml b/pom.xml index 64e3125..a36d12f 100644 --- a/pom.xml +++ b/pom.xml @@ -7,11 +7,11 @@ nl.first8.keycloak.broker idp-saml2-extended - KeyCloak: SAML v2.0 - Extended + Keycloak: SAML v2.0 - Extended SAML v2.0 extensions that adds more configuration options to connect to SAML Service Providers. - 1.1-SNAPSHOT-26 + 26.0 17 @@ -29,6 +29,7 @@ + ${project.artifactId}-${project.version}-${git.commit.id.abbrev} ${project.basedir}/src/main/java ${project.basedir}/target @@ -46,6 +47,7 @@ revision + validate @@ -156,6 +158,9 @@ org.apache.maven.plugins maven-surefire-plugin 3.2.5 + + -Djava.util.logging.manager=org.jboss.logmanager.LogManager + @@ -168,6 +173,9 @@ spotbugs + + ${skipSpotBugs} + diff --git a/src/main/java/nl/first8/keycloak/broker/saml/SAMLEndpoint.java b/src/main/java/nl/first8/keycloak/broker/saml/SAMLEndpoint.java index 3d88877..7f036e9 100644 --- a/src/main/java/nl/first8/keycloak/broker/saml/SAMLEndpoint.java +++ b/src/main/java/nl/first8/keycloak/broker/saml/SAMLEndpoint.java @@ -271,7 +271,7 @@ protected Response handleSamlRequest(String samlRequest, String relayState) { RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject(); // validate destination if (isDestinationRequired() && - requestAbstractType.getDestination() == null && containsUnencryptedSignature(holder)) { + requestAbstractType.getDestination() == null && containsUnencryptedSignature(holder)) { event.event(EventType.IDENTITY_PROVIDER_RESPONSE); event.detail(Details.REASON, Errors.MISSING_REQUIRED_DESTINATION); event.error(Errors.INVALID_REQUEST); @@ -313,10 +313,10 @@ protected Response logoutRequest(LogoutRequestType request, String relayState) { if (request.getSessionIndex() == null || request.getSessionIndex().isEmpty()) { AtomicReference ref = new AtomicReference<>(request); session.sessions().getUserSessionByBrokerUserIdStream(realm, brokerUserId) - .filter(userSession -> userSession.getState() != UserSessionModel.State.LOGGING_OUT && - userSession.getState() != UserSessionModel.State.LOGGED_OUT) - .collect(Collectors.toList()) // collect to avoid concurrent modification as backchannelLogout removes the user sessions. - .forEach(processLogout(ref)); + .filter(userSession -> userSession.getState() != UserSessionModel.State.LOGGING_OUT && + userSession.getState() != UserSessionModel.State.LOGGED_OUT) + .collect(Collectors.toList()) // collect to avoid concurrent modification as backchannelLogout removes the user sessions. + .forEach(processLogout(ref)); request = ref.get(); } else { @@ -347,14 +347,14 @@ protected Response logoutRequest(LogoutRequestType request, String relayState) { builder.destination(config.getSingleLogoutServiceUrl()); builder.issuer(issuerURL); org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder binding = new org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder(session) - .relayState(relayState); + .relayState(relayState); boolean postBinding = config.isPostBindingLogout(); if (config.isWantAuthnRequestsSigned()) { KeyManager.ActiveRsaKey keys = session.keys().getActiveRsaKey(realm); String keyName = config.getXmlSigKeyInfoKeyNameTransformer().getKeyName(keys.getKid(), keys.getCertificate()); binding.signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate()) - .signatureAlgorithm(provider.getSignatureAlgorithm()) - .signDocument(); + .signatureAlgorithm(provider.getSignatureAlgorithm()) + .signDocument(); if (!postBinding && config.isAddExtensionsElementWithKeyInfo()) { // Only include extension if REDIRECT binding and signing whole SAML protocol message builder.addExtension(new KeycloakKeySamlExtensionGenerator(keyName)); } @@ -394,7 +394,6 @@ private String getEntityId(UriInfo uriInfo, RealmModel realm) { } protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder holder, ResponseType responseType, String relayState, String clientId) { - try { AuthenticationSessionModel authSession; if (StringUtil.isNotBlank(clientId)) { @@ -447,10 +446,11 @@ protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder h assertionElement = DocumentUtil.getElement(holder.getSamlDocument(), new QName(JBossSAMLConstants.ASSERTION.get())); } + logger.trace("Validating the response Issuer"); // Validate the response Issuer final String responseIssuer = responseType.getIssuer() != null ? responseType.getIssuer().getValue() : null; final boolean responseIssuerValidationSuccess = config.getIdpEntityId() == null || - (responseIssuer != null && responseIssuer.equals(config.getIdpEntityId())); + (responseIssuer != null && responseIssuer.equals(config.getIdpEntityId())); if (!responseIssuerValidationSuccess) { logger.errorf("Response Issuer validation failed: expected %s, actual %s", config.getIdpEntityId(), responseIssuer); event.event(EventType.IDENTITY_PROVIDER_RESPONSE); @@ -473,6 +473,7 @@ protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder h final boolean signatureNotValid = signed && config.isValidateSignature() && !AssertionUtil.isSignatureValid(assertionElement, getIDPKeyLocator()); final boolean hasNoSignatureWhenRequired = !signed && config.isValidateSignature() && !containsUnencryptedSignature(holder); + if (assertionSignatureNotExistsWhenRequired || signatureNotValid || hasNoSignatureWhenRequired) { logger.error("validation failed"); event.event(EventType.IDENTITY_PROVIDER_RESPONSE); @@ -492,10 +493,11 @@ protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder h AssertionType assertion = responseType.getAssertions().get(0).getAssertion(); + logger.trace("Validating the assertion issuer"); // Validate the assertion Issuer final String assertionIssuer = assertion.getIssuer() != null ? assertion.getIssuer().getValue() : null; final boolean assertionIssuerValidationSuccess = config.getIdpEntityId() == null || - (assertionIssuer != null && assertionIssuer.equals(config.getIdpEntityId())); + (assertionIssuer != null && assertionIssuer.equals(config.getIdpEntityId())); if (!assertionIssuerValidationSuccess) { logger.errorf("Assertion Issuer validation failed: expected %s, actual %s", config.getIdpEntityId(), assertionIssuer); event.event(EventType.IDENTITY_PROVIDER_RESPONSE); @@ -513,7 +515,7 @@ protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder h return ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, Messages.INVALID_REQUESTER); } - BrokeredIdentityContext identity = new BrokeredIdentityContext(principal,config); + BrokeredIdentityContext identity = new BrokeredIdentityContext(principal, config); identity.getContextData().put(SAML_LOGIN_RESPONSE, responseType); identity.getContextData().put(SAML_ASSERTION, assertion); identity.setAuthenticationSession(authSession); @@ -529,8 +531,9 @@ protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder h identity.setToken(samlResponse); } + ConditionsValidator.Builder cvb = new ConditionsValidator.Builder(assertion.getID(), assertion.getConditions(), destinationValidator) - .clockSkewInMillis(1000 * config.getAllowedClockSkew()); + .clockSkewInMillis(1000 * config.getAllowedClockSkew()); try { String issuerURL = getEntityId(session.getContext().getUri(), realm); cvb.addAllowedAudience(URI.create(issuerURL)); @@ -557,6 +560,7 @@ protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder h break; } } + if (assertion.getAttributeStatements() != null) { String email = getX500Attribute(assertion, X500SAMLProfileConstants.EMAIL); if (email != null) { @@ -568,12 +572,15 @@ protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder h String brokerUserId = config.getAlias() + "." + principal; identity.setBrokerUserId(brokerUserId); identity.setIdp(provider); + + if (authn != null && authn.getSessionIndex() != null) { String brokerSessionId = config.getAlias() + "." + authn.getSessionIndex(); logger.debugf("Set broker SessionID to \"%s\".", brokerSessionId); identity.setBrokerSessionId(brokerSessionId); } + logger.trace("handleLoginResponse finished succesfully."); return callback.authenticated(identity); } catch (WebApplicationException e) { return e.getResponse(); @@ -595,8 +602,8 @@ private AuthenticationSessionModel samlIdpInitiatedSSO(final String clientUrlNam event.event(EventType.LOGIN); CacheControlUtil.noBackButtonCacheControlHeader(session); Optional oClient = SAMLEndpoint.this.session.clients() - .searchClientsByAttributes(realm, Collections.singletonMap(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME, clientUrlName), 0, 1) - .findFirst(); + .searchClientsByAttributes(realm, Collections.singletonMap(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME, clientUrlName), 0, 1) + .findFirst(); if (!oClient.isPresent()) { event.error(Errors.CLIENT_NOT_FOUND); @@ -619,10 +626,10 @@ private AuthenticationSessionModel samlIdpInitiatedSSO(final String clientUrlNam private boolean isSuccessfulSamlResponse(ResponseType responseType) { return responseType != null - && responseType.getStatus() != null - && responseType.getStatus().getStatusCode() != null - && responseType.getStatus().getStatusCode().getValue() != null - && Objects.equals(responseType.getStatus().getStatusCode().getValue().toString(), JBossSAMLURIConstants.STATUS_SUCCESS.get()); + && responseType.getStatus() != null + && responseType.getStatus().getStatusCode() != null + && responseType.getStatus().getStatusCode().getValue() != null + && Objects.equals(responseType.getStatus().getStatusCode().getValue().toString(), JBossSAMLURIConstants.STATUS_SUCCESS.get()); } @@ -649,7 +656,7 @@ public Response handleSamlResponse(String samlResponse, String relayState, Strin // validate destination if (isDestinationRequired() - && statusResponse.getDestination() == null && containsUnencryptedSignature(holder)) { + && statusResponse.getDestination() == null && containsUnencryptedSignature(holder)) { logger.warnf("Destination %s required, destination (%s) is NULL or Holder contains unencrypted signature (%s)", (isDestinationRequired()) ? "is" : "is not", statusResponse.getDestination(), containsUnencryptedSignature(holder)); event.event(EventType.IDENTITY_PROVIDER_RESPONSE); event.detail(Details.REASON, Errors.MISSING_REQUIRED_DESTINATION); @@ -663,7 +670,9 @@ public Response handleSamlResponse(String samlResponse, String relayState, Strin event.error(Errors.INVALID_SAML_RESPONSE); return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST); } + logger.trace("Right before handleSamlResponse's if (config.isValidateSignature())"); if (config.isValidateSignature()) { + logger.trace("TRUE: if (config.isValidateSignature())"); try { if (isArtifactResponse) { logger.debugf("Verifying signature for %s", GeneralConstants.SAML_ARTIFACT_RESPONSE_KEY); @@ -687,15 +696,13 @@ public Response handleSamlResponse(String samlResponse, String relayState, Strin logger.debug("SAML Response was NOT of type ResponseType so calling logout."); return handleLogoutResponse(holder, statusResponse, relayState); } - - } private ResponseType convertToResponseType(StatusResponseType statusResponse) { ResponseType responseType; if (statusResponse instanceof org.keycloak.dom.saml.v2.protocol.ResponseType) { org.keycloak.dom.saml.v2.protocol.ResponseType kcResponseType = - (org.keycloak.dom.saml.v2.protocol.ResponseType) ((ArtifactResponseType) statusResponse).getAny(); + (org.keycloak.dom.saml.v2.protocol.ResponseType) ((ArtifactResponseType) statusResponse).getAny(); responseType = new ResponseType(kcResponseType.getID(), kcResponseType.getIssueInstant()); responseType.setExtensions(kcResponseType.getExtensions()); responseType.setInResponseTo(kcResponseType.getInResponseTo()); @@ -787,6 +794,7 @@ protected void verifySignature(String key, SAMLDocumentHolder documentHolder) th protected SAMLDocumentHolder extractRequestDocument(String samlRequest) { return SAMLRequestParser.parseRequestPostBinding(samlRequest); } + @Override protected SAMLDocumentHolder extractResponseDocument(String response) { byte[] samlBytes = response.getBytes(); @@ -893,15 +901,15 @@ private String getPrincipal(AssertionType assertion) { private String getFirstMatchingAttribute(AssertionType assertion, Predicate predicate) { return assertion.getAttributeStatements().stream() - .map(AttributeStatementType::getAttributes) - .flatMap(Collection::stream) - .map(AttributeStatementType.ASTChoiceType::getAttribute) - .filter(predicate) - .map(AttributeType::getAttributeValue) - .flatMap(Collection::stream) - .findFirst() - .map(Object::toString) - .orElse(null); + .map(AttributeStatementType::getAttributes) + .flatMap(Collection::stream) + .map(AttributeStatementType.ASTChoiceType::getAttribute) + .filter(predicate) + .map(AttributeType::getAttributeValue) + .flatMap(Collection::stream) + .findFirst() + .map(Object::toString) + .orElse(null); } private String expectedPrincipalType() { @@ -979,7 +987,6 @@ private boolean validateInResponseToAttribute(ResponseType responseType, String } } } - return true; } } diff --git a/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProvider.java b/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProvider.java index 73b7829..ff325c2 100644 --- a/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProvider.java +++ b/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProvider.java @@ -13,6 +13,7 @@ import nl.first8.keycloak.saml.common.constants.GeneralConstants; import nl.first8.keycloak.saml.processing.api.saml.v2.request.SAML2Request; import nl.first8.keycloak.saml.processing.core.saml.v2.writers.SAMLMetadataWriter; +import nl.first8.keycloak.saml.SAML2AuthnRequestBuilder; import org.jboss.logging.Logger; import org.keycloak.broker.provider.*; import org.keycloak.broker.provider.util.SimpleHttp; @@ -104,8 +105,8 @@ public Response performLogin(AuthenticationRequest request) { } SAML2RequestedAuthnContextBuilder requestedAuthnContext = - new SAML2RequestedAuthnContextBuilder() - .setComparison(getConfig().getAuthnContextComparisonType()); + new SAML2RequestedAuthnContextBuilder() + .setComparison(getConfig().getAuthnContextComparisonType()); for (String authnContextClassRef : getAuthnContextClassRefUris()) requestedAuthnContext.addAuthnContextClassRef(authnContextClassRef); @@ -124,20 +125,25 @@ public Response performLogin(AuthenticationRequest request) { if (protocol.requireReauthentication(null, request.getAuthenticationSession())) forceAuthn = Boolean.TRUE; SAML2AuthnRequestBuilder authnRequestBuilder = new SAML2AuthnRequestBuilder() - .assertionConsumerUrl(assertionConsumerServiceUrl) - .destination(destinationUrl) - .issuer(issuerURL) - .forceAuthn(forceAuthn) - .protocolBinding(protocolBinding) - .nameIdPolicy(SAML2NameIDPolicyBuilder - .format(nameIDPolicyFormat) - .setAllowCreate(allowCreate)) - .attributeConsumingServiceIndex(attributeConsumingServiceIndex) - .requestedAuthnContext(requestedAuthnContext) - .subject(loginHint); + .destination(destinationUrl) + .issuer(issuerURL) + .forceAuthn(forceAuthn) + .protocolBinding(protocolBinding) + .nameIdPolicy(SAML2NameIDPolicyBuilder + .format(nameIDPolicyFormat) + .setAllowCreate(allowCreate)) + .attributeConsumingServiceIndex(attributeConsumingServiceIndex) + .requestedAuthnContext(requestedAuthnContext) + .subject(loginHint); + Integer assertionConsumingServiceIndex = getConfig().getAssertionConsumingServiceIndex(); + if(assertionConsumingServiceIndex != null) { + authnRequestBuilder.assertionConsumerIndex(assertionConsumingServiceIndex); + } else { + authnRequestBuilder.assertionConsumerUrl(assertionConsumerServiceUrl); + } org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder binding = new org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder(session) - .relayState(request.getState().getEncoded()); + .relayState(request.getState().getEncoded()); boolean postBinding = getConfig().isPostBindingAuthnRequest(); logger.debugf("Use %s for AuthNRequest", (postBinding ? "PostBinding" : "RedirectBinding")); @@ -148,8 +154,8 @@ public Response performLogin(AuthenticationRequest request) { String keyName = getConfig().getXmlSigKeyInfoKeyNameTransformer().getKeyName(keys.getKid(), keys.getCertificate()); logger.debugf("Signing using key: %s", keyName); binding.signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate()) - .signatureAlgorithm(getSignatureAlgorithm()) - .signDocument(); + .signatureAlgorithm(getSignatureAlgorithm()) + .signDocument(); if (! postBinding && getConfig().isAddExtensionsElementWithKeyInfo()) { // Only include extension if REDIRECT binding and signing whole SAML protocol message authnRequestBuilder.addExtension(new KeycloakKeySamlExtensionGenerator(keyName)); } @@ -246,8 +252,8 @@ public void backchannelLogout(KeycloakSession session, UserSessionModel userSess singleLogoutServiceUrl = logoutRequest.getDestination().toString(); } int status = SimpleHttp.doPost(singleLogoutServiceUrl, session) - .param(GeneralConstants.SAML_REQUEST_KEY, binding.postBinding(SAML2Request.convert(logoutRequest)).encoded()) - .param(GeneralConstants.RELAY_STATE, userSession.getId()).asStatus(); + .param(GeneralConstants.SAML_REQUEST_KEY, binding.postBinding(SAML2Request.convert(logoutRequest)).encoded()) + .param(GeneralConstants.RELAY_STATE, userSession.getId()).asStatus(); boolean success = status >= 200 && status < 400; if (!success) { logger.warn("Failed saml backchannel broker logout to: " + singleLogoutServiceUrl); @@ -290,11 +296,11 @@ protected LogoutRequestType buildLogoutRequest(UserSessionModel userSession, String singleLogoutServiceUrl, NodeGenerator... extensions) throws ConfigurationException { SAML2LogoutRequestBuilder logoutBuilder = new SAML2LogoutRequestBuilder() - .assertionExpiration(realm.getAccessCodeLifespan()) - .issuer(getEntityId(uriInfo, realm)) - .sessionIndex(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SESSION_INDEX)) - .nameId(NameIDType.deserializeFromString(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT_NAMEID))) - .destination(singleLogoutServiceUrl); + .assertionExpiration(realm.getAccessCodeLifespan()) + .issuer(getEntityId(uriInfo, realm)) + .sessionIndex(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SESSION_INDEX)) + .nameId(NameIDType.deserializeFromString(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT_NAMEID))) + .destination(singleLogoutServiceUrl); LogoutRequestType logoutRequest = logoutBuilder.createLogoutRequest(); for (NodeGenerator extension : extensions) { logoutBuilder.addExtension(extension); @@ -307,13 +313,13 @@ protected LogoutRequestType buildLogoutRequest(UserSessionModel userSession, private JaxrsSAML2BindingBuilder buildLogoutBinding(KeycloakSession session, UserSessionModel userSession, RealmModel realm) { JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder(session, getConfig()) - .relayState(userSession.getId()); + .relayState(userSession.getId()); if (getConfig().isWantAuthnRequestsSigned()) { KeyManager.ActiveRsaKey keys = session.keys().getActiveRsaKey(realm); String keyName = getConfig().getXmlSigKeyInfoKeyNameTransformer().getKeyName(keys.getKid(), keys.getCertificate()); binding.signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate()) - .signatureAlgorithm(getSignatureAlgorithm()) - .signDocument(); + .signatureAlgorithm(getSignatureAlgorithm()) + .signDocument(); } return binding; } @@ -324,8 +330,8 @@ public String resolveArtifact(String artifact, String issuerURL, RealmModel real String response = ""; try { SAML2ArtifactResolutionBuilder builder = new SAML2ArtifactResolutionBuilder() - .artifact(artifact) - .issuer(issuerURL); + .artifact(artifact) + .issuer(issuerURL); JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder(session, getConfig()); logger.debugf("Sign ArtifactResolve request? -> %s", getConfig().isSignArtifactResolutionRequest()); @@ -370,30 +376,30 @@ public Response export(UriInfo uriInfo, RealmModel realm, String format) { List endpoints = new ArrayList(); endpoints.add(uriInfo.getBaseUriBuilder() - .path("realms").path(realm.getName()) - .path("broker") - .path(getConfig().getAlias()) - .path("endpoint") - .build()); + .path("realms").path(realm.getName()) + .path("broker") + .path(getConfig().getAlias()) + .path("endpoint") + .build()); List linkedProviders = getConfig().getLinkedProviders(); logger.debugf("Found %d number of linked providers.", linkedProviders.size()); if (!linkedProviders.isEmpty()) { for (String linkedProvider : linkedProviders) { endpoints.add(uriInfo.getBaseUriBuilder() - .path("realms").path(realm.getName()) - .path("broker") - .path(linkedProvider) - .path("endpoint") - .build()); + .path("realms").path(realm.getName()) + .path("broker") + .path(linkedProvider) + .path("endpoint") + .build()); } } URI artifactEndpoint = uriInfo.getBaseUriBuilder() - .path("realms").path(realm.getName()) - .path("broker") - .path(getConfig().getAlias()) - .path("endpoint") - .build(); + .path("realms").path(realm.getName()) + .path("broker") + .path(getConfig().getAlias()) + .path("endpoint") + .build(); boolean wantAuthnRequestsSigned = getConfig().isWantAuthnRequestsSigned(); boolean wantAssertionsSigned = getConfig().isWantAssertionsSigned(); @@ -404,39 +410,39 @@ public Response export(UriInfo uriInfo, RealmModel realm, String format) { // We export all keys for algorithm RS256, both active and passive so IDP is able to verify signature even // if a key rotation happens in the meantime List signingKeys = session.keys().getKeysStream(realm, KeyUse.SIG, Algorithm.RS256) - .filter(key -> key.getCertificate() != null) - .sorted(SamlService::compareKeys) - .map(key -> { - try { - return SPMetadataDescriptor.buildKeyInfoElement(key.getKid(), PemUtils.encodeCertificate(key.getCertificate())); - } catch (ParserConfigurationException e) { - logger.warn("Failed to export SAML SP Metadata!", e); - throw new RuntimeException(e); - } - }) - .map(key -> SPMetadataDescriptor.buildKeyDescriptorType(key, KeyTypes.SIGNING, null)) - .collect(Collectors.toList()); + .filter(key -> key.getCertificate() != null) + .sorted(SamlService::compareKeys) + .map(key -> { + try { + return SPMetadataDescriptor.buildKeyInfoElement(key.getKid(), PemUtils.encodeCertificate(key.getCertificate())); + } catch (ParserConfigurationException e) { + logger.warn("Failed to export SAML SP Metadata!", e); + throw new RuntimeException(e); + } + }) + .map(key -> SPMetadataDescriptor.buildKeyDescriptorType(key, KeyTypes.SIGNING, null)) + .collect(Collectors.toList()); // We export only active ENC keys so IDP uses different key as soon as possible if a key rotation happens String encAlg = getConfig().getEncryptionAlgorithm(); List encryptionKeys = session.keys().getKeysStream(realm) - .filter(key -> key.getStatus().isActive() && KeyUse.ENC.equals(key.getUse()) - && (encAlg == null || Objects.equals(encAlg, key.getAlgorithmOrDefault())) - && SAMLEncryptionAlgorithms.forKeycloakIdentifier(key.getAlgorithm()) != null - && key.getCertificate() != null) - .sorted(SamlService::compareKeys) - .map(key -> { - Element keyInfo; - try { - keyInfo = SPMetadataDescriptor.buildKeyInfoElement(key.getKid(), PemUtils.encodeCertificate(key.getCertificate())); - } catch (ParserConfigurationException e) { - logger.warn("Failed to export SAML SP Metadata!", e); - throw new RuntimeException(e); - } + .filter(key -> key.getStatus().isActive() && KeyUse.ENC.equals(key.getUse()) + && (encAlg == null || Objects.equals(encAlg, key.getAlgorithmOrDefault())) + && SAMLEncryptionAlgorithms.forKeycloakIdentifier(key.getAlgorithm()) != null + && key.getCertificate() != null) + .sorted(SamlService::compareKeys) + .map(key -> { + Element keyInfo; + try { + keyInfo = SPMetadataDescriptor.buildKeyInfoElement(key.getKid(), PemUtils.encodeCertificate(key.getCertificate())); + } catch (ParserConfigurationException e) { + logger.warn("Failed to export SAML SP Metadata!", e); + throw new RuntimeException(e); + } - return SPMetadataDescriptor.buildKeyDescriptorType(keyInfo, KeyTypes.ENCRYPTION, SAMLEncryptionAlgorithms.forKeycloakIdentifier(key.getAlgorithm()).getXmlEncIdentifiers()); - }) - .collect(Collectors.toList()); + return SPMetadataDescriptor.buildKeyDescriptorType(keyInfo, KeyTypes.ENCRYPTION, SAMLEncryptionAlgorithms.forKeycloakIdentifier(key.getAlgorithm()).getXmlEncIdentifiers()); + }) + .collect(Collectors.toList()); // Prepare the metadata descriptor model StringWriter sw = new StringWriter(); XMLStreamWriter writer = StaxUtil.getXMLStreamWriter(sw); @@ -448,28 +454,28 @@ public Response export(UriInfo uriInfo, RealmModel realm, String format) { } SPMetadataDescriptorBuilder spMetadataDescriptorBuilder = new SPMetadataDescriptorBuilder() - .loginBinding(authnResponseBinding) - .logoutBinding(logoutBinding) - .assertionEndpoints(endpoints) - .defaultAssertionEndpoint(defaultAssertionEndpointIndex) - .logoutEndpoints(endpoints) - .wantAuthnRequestsSigned(wantAuthnRequestsSigned) - .wantAssertionsSigned(wantAssertionsSigned) - .wantAssertionsEncrypted(wantAssertionsEncrypted) - .entityId(entityId) - .nameIDPolicyFormat(nameIDPolicyFormat) - .signingCerts(signingKeys) - .encryptionCerts(encryptionKeys); + .loginBinding(authnResponseBinding) + .logoutBinding(logoutBinding) + .assertionEndpoints(endpoints) + .defaultAssertionEndpoint(defaultAssertionEndpointIndex) + .logoutEndpoints(endpoints) + .wantAuthnRequestsSigned(wantAuthnRequestsSigned) + .wantAssertionsSigned(wantAssertionsSigned) + .wantAssertionsEncrypted(wantAssertionsEncrypted) + .entityId(entityId) + .nameIDPolicyFormat(nameIDPolicyFormat) + .signingCerts(signingKeys) + .encryptionCerts(encryptionKeys); if (getConfig().isIncludeArtifactResolutionServiceMetadata()) { spMetadataDescriptorBuilder.artifactResolutionBinding(artifactBinding) - .artifactResolutionEndpoint(artifactEndpoint); + .artifactResolutionEndpoint(artifactEndpoint); } if (getConfig().getMetadataValidUntilUnit() != null && getConfig().getMetadataValidUntilPeriod() != null) { logger.debugf("Valid Until set for Metadata. Setting valid until current date + %s %s", - getConfig().getMetadataValidUntilUnit(), getConfig().getMetadataValidUntilPeriod()); + getConfig().getMetadataValidUntilUnit(), getConfig().getMetadataValidUntilPeriod()); spMetadataDescriptorBuilder - .metadataValidUntilUnit(getConfig().getMetadataValidUntilUnit()) - .metadataValidUntilPeriod(getConfig().getMetadataValidUntilPeriod()); + .metadataValidUntilUnit(getConfig().getMetadataValidUntilUnit()) + .metadataValidUntilPeriod(getConfig().getMetadataValidUntilPeriod()); } EntityDescriptorType entityDescriptor = spMetadataDescriptorBuilder.build(); @@ -510,8 +516,8 @@ public Response export(UriInfo uriInfo, RealmModel realm, String format) { } boolean alreadyPresent = attributeConsumingService.getRequestedAttribute().stream() - .anyMatch(t -> (attributeName == null || attributeName.equalsIgnoreCase(t.getName())) && - (attributeFriendlyName == null || attributeFriendlyName.equalsIgnoreCase(t.getFriendlyName()))); + .anyMatch(t -> (attributeName == null || attributeName.equalsIgnoreCase(t.getName())) && + (attributeFriendlyName == null || attributeFriendlyName.equalsIgnoreCase(t.getFriendlyName()))); if (!alreadyPresent) { logger.debugf("%s not present adding to Attribute Consuming Service", attributeName); diff --git a/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProviderConfig.java b/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProviderConfig.java index f68aaaa..4a26552 100644 --- a/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProviderConfig.java +++ b/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProviderConfig.java @@ -60,8 +60,8 @@ public class SAMLIdentityProviderConfig extends org.keycloak.broker.saml.SAMLIde public static final String CHAR_SET = "charSet"; public static final String METADATA_VALID_UNTIL_UNIT = "metadataValidUntilUnit"; public static final String METADATA_VALID_UNTIL_PERIOD = "metadataValidUntilPeriod"; + public static final String ARTIFACT_BINDING_RESPONSE = "artifactBindingResponse"; public static final String ARTIFACT_RESOLUTION_MUTUAL_TLS = "mutualTls"; - public static final String IGNORE_SAML_ADVICE_NODES = "ignoreSamlAdviceNodes"; public static final String AUTHN_REQUEST_SCOPING = "scoping"; public static final String LINKED_PROVIDERS = "linkedProviders"; public static final String SERVICE_NAME = "serviceName"; @@ -114,6 +114,14 @@ public void setArtifactResolution(boolean artifactResolution) { getConfig().put(ARTIFACT_RESOLUTION, String.valueOf(artifactResolution)); } + public boolean isArtifactBindingResponse() { + return Boolean.parseBoolean(getConfig().get(ARTIFACT_BINDING_RESPONSE)); + } + + public void setArtifactBindingResponse(boolean artifactBindingResponse) { + getConfig().put(ARTIFACT_BINDING_RESPONSE, String.valueOf(artifactBindingResponse)); + } + public boolean isIncludeArtifactResolutionServiceMetadata() { return Boolean.parseBoolean(getConfig().get(ARTIFACT_RESOLUTION_SERVICE_METADATA)); } @@ -167,7 +175,7 @@ public Integer getMetadataValidUntilPeriod() { } public void setMetadataValidUntilPeriod(Integer period) { - getConfig().put(METADATA_VALID_UNTIL_UNIT, String.valueOf(period)); + getConfig().put(METADATA_VALID_UNTIL_PERIOD, String.valueOf(period)); } public boolean isMutualTLS() { @@ -178,14 +186,6 @@ public void setMutualTls(boolean mutualTls) { getConfig().put(ARTIFACT_RESOLUTION_MUTUAL_TLS, String.valueOf(mutualTls)); } - public void setIgnoreSamlAdviceNodes(boolean ignoreSamlAdviceNodes) { - getConfig().put(IGNORE_SAML_ADVICE_NODES, String.valueOf(ignoreSamlAdviceNodes)); - } - - public boolean isIgnoreSamlAdviceNodes() { - return Boolean.parseBoolean(getConfig().get(IGNORE_SAML_ADVICE_NODES)); - } - public String getScoping() { return this.getConfig().get(AUTHN_REQUEST_SCOPING); } @@ -245,8 +245,6 @@ public Integer getAttributeConsumingServiceIndex() { } } return result; - - } public void setAttributeConsumingServiceIndex(Integer attributeConsumingServiceIndex) { diff --git a/src/main/java/nl/first8/keycloak/protocol/saml/SamlProtocolUtils.java b/src/main/java/nl/first8/keycloak/protocol/saml/SamlProtocolUtils.java index 11edd99..2fb4299 100644 --- a/src/main/java/nl/first8/keycloak/protocol/saml/SamlProtocolUtils.java +++ b/src/main/java/nl/first8/keycloak/protocol/saml/SamlProtocolUtils.java @@ -9,6 +9,7 @@ import java.security.cert.X509Certificate; import jakarta.ws.rs.core.MultivaluedMap; import jakarta.ws.rs.core.UriInfo; +import nl.first8.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature; import org.jboss.logging.Logger; import org.keycloak.common.VerificationException; import org.keycloak.common.util.PemUtils; @@ -34,7 +35,6 @@ import org.keycloak.saml.common.util.DocumentUtil; import org.keycloak.saml.common.util.StaxUtil; import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request; -import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature; import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator; import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder; import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; @@ -44,10 +44,8 @@ import org.keycloak.saml.processing.web.util.RedirectBindingUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; -public class SamlProtocolUtils { - - private static final Logger logger = Logger.getLogger(org.keycloak.protocol.saml.SamlProtocolUtils.class); +public class SamlProtocolUtils { /** * Verifies a signature of the given SAML document using settings for the given client. * Throws an exception if the client signature is expected to be present as per the client @@ -151,7 +149,7 @@ public static void verifyRedirectSignature(SAMLDocumentHolder documentHolder, Ke String decodedAlgorithm = RedirectBindingUtil.urlDecode(encodedParams.getFirst(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY)); SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.getFromXmlMethod(decodedAlgorithm); if (!RedirectBindingSignatureUtil.validateRedirectBindingSignature(signatureAlgorithm, - rawQuery.getBytes("UTF-8"), decodedSignature, locator, keyId)) { + rawQuery.getBytes("UTF-8"), decodedSignature, locator, keyId)) { throw new VerificationException("Invalid query param signature"); } } catch (Exception e) { @@ -199,7 +197,7 @@ private static String getMessageSigningKeyId(SAML2Object doc) { */ public static ArtifactResponseType buildArtifactResponse(SAML2Object samlObject, NameIDType issuer, URI statusCode) throws ConfigurationException, ProcessingException { ArtifactResponseType artifactResponse = new ArtifactResponseType(IDGenerator.create("ID_"), - XMLTimeUtil.getIssueInstant()); + XMLTimeUtil.getIssueInstant()); // Status StatusType statusType = new StatusType(); @@ -254,7 +252,7 @@ public static ArtifactResponseType buildArtifactResponse(Document document) thro * @throws ProcessingException */ public static Document convert(ArtifactResponseType responseType) throws ProcessingException, ConfigurationException, - ParsingException { + ParsingException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); SAMLResponseWriter writer = new SAMLResponseWriter(StaxUtil.getXMLStreamWriter(bos)); writer.write(responseType); diff --git a/src/main/java/nl/first8/keycloak/saml/SAMLRequestParser.java b/src/main/java/nl/first8/keycloak/saml/SAMLRequestParser.java index e7b22d9..9f58fe9 100644 --- a/src/main/java/nl/first8/keycloak/saml/SAMLRequestParser.java +++ b/src/main/java/nl/first8/keycloak/saml/SAMLRequestParser.java @@ -7,7 +7,7 @@ import org.keycloak.common.util.StreamUtil; import org.keycloak.saml.common.PicketLinkLogger; -import org.keycloak.saml.common.PicketLinkLoggerFactory; +import nl.first8.keycloak.saml.common.PicketLinkLoggerFactory; import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request; import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder; import org.keycloak.saml.processing.web.util.PostBindingUtil; @@ -18,7 +18,7 @@ import java.io.InputStream; public class SAMLRequestParser { - private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); + private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(Logger.getLogger(SAMLRequestParser.class)); protected static Logger log = Logger.getLogger(SAMLRequestParser.class); public static SAMLDocumentHolder parseRequestRedirectBinding(String samlMessage) { diff --git a/src/main/java/nl/first8/keycloak/saml/common/DefaultPicketLinkLogger.java b/src/main/java/nl/first8/keycloak/saml/common/DefaultPicketLinkLogger.java new file mode 100644 index 0000000..f6ed462 --- /dev/null +++ b/src/main/java/nl/first8/keycloak/saml/common/DefaultPicketLinkLogger.java @@ -0,0 +1,2386 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package nl.first8.keycloak.saml.common; + +import jakarta.xml.ws.WebServiceException; +import org.jboss.logging.Logger; +import org.keycloak.saml.common.ErrorCodes; +import org.keycloak.saml.common.PicketLinkLogger; +import org.keycloak.saml.common.constants.GeneralConstants; +import org.keycloak.saml.common.constants.WSTrustConstants; +import org.keycloak.saml.common.exceptions.*; +import org.keycloak.saml.common.exceptions.fed.*; +import org.w3c.dom.Element; + +import javax.security.auth.login.LoginException; +import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.stream.Location; +import java.io.IOException; +import java.security.GeneralSecurityException; + +/** + * @author Pedro Silva + * + */ + +/**@author Pedro Silva */ +public class DefaultPicketLinkLogger implements PicketLinkLogger { + + private final Logger logger; + + DefaultPicketLinkLogger() { + logger = Logger.getLogger(PicketLinkLogger.class.getPackage().getName()); + } + + public DefaultPicketLinkLogger(Logger logger) { + this.logger = logger; + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#info(java.lang.String) + */ + @Override + public void info(String message) { + if (logger.isInfoEnabled()) { + logger.info(message); + } + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#debug(java.lang.String) + */ + @Override + public void debug(String message) { + if (logger.isDebugEnabled()) { + logger.debug(message); + } + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#trace(java.lang.String) + */ + @Override + public void trace(String message) { + if (logger.isTraceEnabled()) { + logger.trace(message); + } + } + + /* + *(non-Javadoc) + * + * @see org.picketlink.identity.federation.PicketLinkLogger#trace(java.lang.String, java.lang.Throwable) + */ + @Override + public void trace(String message, Throwable t) { + if (logger.isTraceEnabled()) { + logger.trace(message, t); + } + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#trace(java.lang.Throwable) + */ + @Override + public void trace(Throwable t) { + if (logger.isTraceEnabled()) { + logger.trace(t.getMessage(), t); + } + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#error(java.lang.Throwable) + */ + @Override + public void error(Throwable t) { + logger.error("Unexpected error", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#nullArgument(java.lang.String) + */ + @Override + public IllegalArgumentException nullArgumentError(String argument) { + return new IllegalArgumentException(ErrorCodes.NULL_ARGUMENT + argument); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#shouldNotBeTheSame(java.lang.String) + */ + @Override + public IllegalArgumentException shouldNotBeTheSameError(String string) { + return new IllegalArgumentException(ErrorCodes.SHOULD_NOT_BE_THE_SAME + + "Only one of isSigningKey and isEncryptionKey should be true"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#resourceNotFound(java.lang.String) + */ + @Override + public ProcessingException resourceNotFound(String resource) { + return new ProcessingException(ErrorCodes.RESOURCE_NOT_FOUND + resource + " could not be loaded"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#processingError(java.lang.Throwable) + */ + @Override + public ProcessingException processingError(Throwable t) { + return new ProcessingException(ErrorCodes.PROCESSING_EXCEPTION, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#unsupportedType(java.lang.String) + */ + @Override + public RuntimeException unsupportedType(String name) { + return new RuntimeException(ErrorCodes.UNSUPPORTED_TYPE + name); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#signatureError(java.lang.Throwable) + */ + @Override + public XMLSignatureException signatureError(Throwable e) { + return new XMLSignatureException(ErrorCodes.SIGNING_PROCESS_FAILURE, e); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#nullValue(java.lang.String) + */ + @Override + public RuntimeException nullValueError(String nullValue) { + return new RuntimeException(ErrorCodes.NULL_VALUE + nullValue); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#notImplementedYet() + */ + @Override + public RuntimeException notImplementedYet(String feature) { + return new RuntimeException(ErrorCodes.NOT_IMPLEMENTED_YET + feature); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#auditNullAuditManager() + */ + @Override + public IllegalStateException auditNullAuditManager() { + return new IllegalStateException(ErrorCodes.AUDIT_MANAGER_NULL); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#isInfoEnabled() + */ + @Override + public boolean isInfoEnabled() { + return logger.isInfoEnabled(); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#auditEvent(java.lang.String) + */ + @Override + public void auditEvent(String auditEvent) { + this.info(auditEvent); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#injectedValueMissing(java.lang.String) + */ + @Override + public RuntimeException injectedValueMissing(String value) { + return new RuntimeException(ErrorCodes.INJECTED_VALUE_MISSING + value); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#keystoreSetup() + */ + @Override + public void keyStoreSetup() { + this.trace("getPublicKey::Keystore is null. so setting it up"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#keyStoreNullStore() + */ + @Override + public IllegalStateException keyStoreNullStore() { + return new IllegalStateException(ErrorCodes.KEYSTOREKEYMGR_NULL_KEYSTORE); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#keyStoreNullPublicKeyForAlias(java.lang.String) + */ + @Override + public void keyStoreNullPublicKeyForAlias(String alias) { + this.trace("No public key found for alias=" + alias); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#keyStoreConfigurationError(java.lang.Throwable) + */ + @Override + public TrustKeyConfigurationException keyStoreConfigurationError(Throwable t) { + return new TrustKeyConfigurationException(t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#keyStoreProcessingError(java.lang.Throwable) + */ + @Override + public TrustKeyProcessingException keyStoreProcessingError(Throwable t) { + return new TrustKeyProcessingException(t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#keyStoreMissingDomainAlias(java.lang.String) + */ + @Override + public IllegalStateException keyStoreMissingDomainAlias(String domain) { + return new IllegalStateException(ErrorCodes.KEYSTOREKEYMGR_DOMAIN_ALIAS_MISSING + domain); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#keyStoreNullSigningKeyPass() + */ + @Override + public RuntimeException keyStoreNullSigningKeyPass() { + return new RuntimeException(ErrorCodes.KEYSTOREKEYMGR_NULL_SIGNING_KEYPASS); + } + + @Override + public RuntimeException keyStoreNullEncryptionKeyPass() { + return new RuntimeException(ErrorCodes.KEYSTOREKEYMGR_NULL_ENCRYPTION_KEYPASS); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#keyStoreNotLocated(java.lang.String) + */ + @Override + public RuntimeException keyStoreNotLocated(String keyStore) { + return new RuntimeException(ErrorCodes.KEYSTOREKEYMGR_KEYSTORE_NOT_LOCATED + keyStore); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#keyStoreNullAlias() + */ + @Override + public IllegalStateException keyStoreNullAlias() { + return new IllegalStateException(ErrorCodes.KEYSTOREKEYMGR_NULL_ALIAS); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parserUnknownEndElement(java.lang.String) + */ + @Override + public RuntimeException parserUnknownEndElement(String endElementName, Location location) { + return new RuntimeException(ErrorCodes.UNKNOWN_END_ELEMENT + endElementName + "::location=" + location); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parseUnknownTag(java.lang.String, javax.xml.stream.Location) + */ + @Override + public RuntimeException parserUnknownTag(String tag, Location location) { + return new RuntimeException(ErrorCodes.UNKNOWN_TAG + tag + "::location=" + location); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parseRequiredAttribute(java.lang.String) + */ + @Override + public ParsingException parserRequiredAttribute(String string) { + return new ParsingException(ErrorCodes.REQD_ATTRIBUTE + string); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parserUnknownStartElement(java.lang.String, + *javax.xml.stream.Location) + */ + @Override + public RuntimeException parserUnknownStartElement(String elementName, Location location) { + return new RuntimeException(ErrorCodes.UNKNOWN_START_ELEMENT + elementName + "::location=" + location); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parserNullStartElement() + */ + @Override + public IllegalStateException parserNullStartElement() { + return new IllegalStateException(ErrorCodes.NULL_START_ELEMENT); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parserUnknownXSI(java.lang.String) + */ + @Override + public ParsingException parserUnknownXSI(String xsiTypeValue) { + return new ParsingException(ErrorCodes.UNKNOWN_XSI + xsiTypeValue); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parserExpectedEndTag(java.lang.String) + */ + @Override + public ParsingException parserExpectedEndTag(String tagName) { + return new ParsingException(ErrorCodes.EXPECTED_END_TAG + tagName); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parserException(java.lang.Exception) + */ + @Override + public ParsingException parserException(Throwable t) { + return new ParsingException(t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parserExpectedTextValue(java.lang.String) + */ + @Override + public ParsingException parserExpectedTextValue(String string) { + return new ParsingException(ErrorCodes.EXPECTED_TEXT_VALUE + "SigningAlias"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parserExpectedXSI(java.lang.String) + */ + @Override + public RuntimeException parserExpectedXSI(String expectedXsi) { + return new RuntimeException(expectedXsi); + } + + @Override + public RuntimeException parserExpectedTag(String tag, String foundElementTag, Integer line, Integer column) { + return new RuntimeException(ErrorCodes.EXPECTED_TAG + " " + tag + ". Found " + foundElementTag + + " at line " + line.toString() + ", column " + column); + } + + @Override + public RuntimeException parserExpectedNamespace(String ns, String foundElementNs) { + return new RuntimeException(ErrorCodes.EXPECTED_NAMESPACE + ns + ">. Found <" + foundElementNs + ">"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parserFailed() + */ + @Override + public RuntimeException parserFailed(String elementName) { + return new RuntimeException(ErrorCodes.FAILED_PARSING + elementName); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parserUnableParsingNullToken() + */ + @Override + public ParsingException parserUnableParsingNullToken() { + return new ParsingException(ErrorCodes.UNABLE_PARSING_NULL_TOKEN); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#parserError(java.lang.Exception) + */ + @Override + public ParsingException parserError(Throwable t) { + return new ParsingException(ErrorCodes.PARSING_ERROR + t.getMessage(), t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#pdpMessageProcessingError(java.lang.Exception) + */ + @Override + public RuntimeException xacmlPDPMessageProcessingError(Throwable t) { + return new RuntimeException(t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#fileNotLocated(java.lang.String) + */ + @Override + public IllegalStateException fileNotLocated(String policyConfigFileName) { + return new IllegalStateException(ErrorCodes.FILE_NOT_LOCATED + policyConfigFileName); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#optionNotSet(java.lang.String) + */ + @Override + public IllegalStateException optionNotSet(String option) { + return new IllegalStateException(ErrorCodes.OPTION_NOT_SET + option); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#securityTokenRegistryNotSpecified() + */ + @Override + public void stsTokenRegistryNotSpecified() { + this.warn("Security Token registry option not specified: Issued Tokens will not be persisted!"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#securityTokenRegistryInvalidType(java.lang.String) + */ + @Override + public void stsTokenRegistryInvalidType(String tokenRegistryOption) { + logger.warn(tokenRegistryOption + " is not an instance of SecurityTokenRegistry - using default registry"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#securityTokenRegistryInstantiationError() + */ + @Override + public void stsTokenRegistryInstantiationError() { + logger.warn("Error instantiating token registry class - using default registry"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#revocationRegistryNotSpecified() + */ + @Override + public void stsRevocationRegistryNotSpecified() { + this.debug("Revocation registry option not specified: cancelled ids will not be persisted!"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#revocationRegistryInvalidType(java.lang.String) + */ + @Override + public void stsRevocationRegistryInvalidType(String registryOption) { + logger.warn(registryOption + " is not an instance of RevocationRegistry - using default registry"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#revocationRegistryInstantiationError() + */ + @Override + public void stsRevocationRegistryInstantiationError() { + logger.warn("Error instantiating revocation registry class - using default registry"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#assertionExpiredError() + */ + @Override + public ProcessingException samlAssertionExpiredError() { + return new ProcessingException(ErrorCodes.EXPIRED_ASSERTION); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#assertionInvalidError() + */ + @Override + public ProcessingException assertionInvalidError() { + return new ProcessingException(ErrorCodes.INVALID_ASSERTION); + } + + @Override + public RuntimeException writerUnknownTypeError(String name) { + return new RuntimeException(ErrorCodes.WRITER_UNKNOWN_TYPE + name); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#writerNullValueError(java.lang.String) + */ + @Override + public ProcessingException writerNullValueError(String value) { + return new ProcessingException(ErrorCodes.WRITER_NULL_VALUE + value); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#writerUnsupportedAttributeValueError(java.lang.String) + */ + @Override + public RuntimeException writerUnsupportedAttributeValueError(String value) { + return new RuntimeException(ErrorCodes.WRITER_UNSUPPORTED_ATTRIB_VALUE + value); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#issuerInfoMissingStatusCodeError() + */ + @Override + public IllegalArgumentException issuerInfoMissingStatusCodeError() { + return new IllegalArgumentException(ErrorCodes.ISSUER_INFO_MISSING_STATUS_CODE); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#classNotLoadedError(java.lang.String) + */ + @Override + public ProcessingException classNotLoadedError(String fqn) { + return new ProcessingException(ErrorCodes.CLASS_NOT_LOADED + fqn); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#couldNotCreateInstance(java.lang.String, java.lang.Exception) + */ + @Override + public ProcessingException couldNotCreateInstance(String fqn, Throwable t) { + return new ProcessingException(ErrorCodes.CANNOT_CREATE_INSTANCE + fqn, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#systemPropertyMissingError(java.lang.String) + */ + @Override + public RuntimeException systemPropertyMissingError(String property) { + return new RuntimeException(ErrorCodes.SYSTEM_PROPERTY_MISSING + property); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#metaDataIdentityProviderLoadingError(java.lang.Exception) + */ + @Override + public void samlMetaDataIdentityProviderLoadingError(Throwable t) { + logger.error("Exception loading the identity providers:", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#metaDataServiceProviderLoadingError(java.lang.Throwable) + */ + @Override + public void samlMetaDataServiceProviderLoadingError(Throwable t) { + logger.error("Exception loading the service providers:", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#signatureAssertionValidationError(java.lang.Exception) + */ + @Override + public void signatureAssertionValidationError(Throwable t) { + logger.error("Cannot validate signature of assertion", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#assertionExpired(java.lang.String) + */ + @Override + public void samlAssertionExpired(String id) { + this.info("Assertion has expired with id=" + id); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#unknownObjectType(java.lang.Object) + */ + @Override + public RuntimeException unknownObjectType(Object attrValue) { + return new RuntimeException(ErrorCodes.UNKNOWN_OBJECT_TYPE + attrValue); + } + + /* + *(non-Javadoc) + * + *@see + *org.picketlink.identity.federation.PicketLinkLogger#configurationError(javax.xml.parsers.ParserConfigurationException) + */ + @Override + public ConfigurationException configurationError(Throwable t) { + return new ConfigurationException(t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#signatureUnknownAlgo(java.lang.String) + */ + @Override + public RuntimeException signatureUnknownAlgo(String algo) { + return new RuntimeException(ErrorCodes.UNKNOWN_SIG_ALGO + algo); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#invalidArgumentError(java.lang.String) + */ + @Override + public IllegalArgumentException invalidArgumentError(String message) { + return new IllegalArgumentException(message); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsNoTokenProviderError(java.lang.String) + */ + @Override + public ProcessingException stsNoTokenProviderError(String configuration, String protocolContext) { + return new ProcessingException(ErrorCodes.STS_NO_TOKEN_PROVIDER + configuration + "][ProtoCtx=" + protocolContext + "]"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsConfigurationFileNotFoundTCL(java.lang.String) + */ + @Override + public void stsConfigurationFileNotFoundTCL(String fileName) { + logger.warn(fileName + " configuration file not found using TCCL"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsConfigurationFileNotFoundClassLoader(java.lang.String) + */ + @Override + public void stsConfigurationFileNotFoundClassLoader(String fileName) { + logger.warn(fileName + " configuration file not found using class loader"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsUsingDefaultConfiguration(java.lang.String) + */ + @Override + public void stsUsingDefaultConfiguration(String fileName) { + logger.warn(fileName + " configuration file not found using URL. Using default configuration values"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsConfigurationFileLoaded(java.lang.String) + */ + @Override + public void stsConfigurationFileLoaded(String fileName) { + this.info(fileName + " configuration file loaded"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsConfigurationFileParsingError(java.lang.Throwable) + */ + @Override + public ConfigurationException stsConfigurationFileParsingError(Throwable t) { + return new ConfigurationException(ErrorCodes.STS_CONFIGURATION_FILE_PARSING_ERROR, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#notSerializableError(java.lang.String) + */ + @Override + public IOException notSerializableError(String message) { + return new IOException(ErrorCodes.NOT_SERIALIZABLE + message); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#trustKeyCreationError() + */ + @Override + public void trustKeyManagerCreationError(Throwable t) { + logger.error("Exception creating TrustKeyManager:", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#error(java.lang.String) + */ + @Override + public void error(String message) { + logger.error(message); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#couldNotGetXMLSchema(java.lang.Throwable) + */ + @Override + public void xmlCouldNotGetSchema(Throwable t) { + logger.error("Cannot get schema", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#isTraceEnabled() + */ + @Override + public boolean isTraceEnabled() { + return logger.isTraceEnabled(); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#isDebugEnabled() + */ + @Override + public boolean isDebugEnabled() { + return logger.isDebugEnabled(); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#jceProviderCouldNotBeLoaded(java.lang.Throwable) + */ + @Override + public void jceProviderCouldNotBeLoaded(String name, Throwable t) { + logger.debug("The provider " + name + " could not be added: ", t); + logger.debug("Check addJceProvider method of org.picketlink.identity.federation.core.util.ProvidersUtil for more info."); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#writerInvalidKeyInfoNullContent() + */ + @Override + public ProcessingException writerInvalidKeyInfoNullContentError() { + return new ProcessingException(ErrorCodes.WRITER_INVALID_KEYINFO_NULL_CONTENT); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#notEqualError(java.lang.String, java.lang.String) + */ + @Override + public RuntimeException notEqualError(String first, String second) { + return new RuntimeException(ErrorCodes.NOT_EQUAL + first + " and " + second); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#wrongTypeError(java.lang.String) + */ + @Override + public IllegalArgumentException wrongTypeError(String message) { + return new IllegalArgumentException(ErrorCodes.WRONG_TYPE + "xmlSource should be a stax source"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#encryptUnknownAlgoError(java.lang.String) + */ + @Override + public RuntimeException encryptUnknownAlgoError(String certAlgo) { + return new RuntimeException(ErrorCodes.UNKNOWN_ENC_ALGO + certAlgo); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#domMissingDocElementError(java.lang.String) + */ + @Override + public IllegalStateException domMissingDocElementError(String element) { + return new IllegalStateException(ErrorCodes.DOM_MISSING_DOC_ELEMENT + element); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#domMissingElementError(java.lang.String) + */ + @Override + public IllegalStateException domMissingElementError(String element) { + return new IllegalStateException(ErrorCodes.DOM_MISSING_ELEMENT + element); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsWSInvalidTokenRequestError() + */ + @Override + public WebServiceException stsWSInvalidTokenRequestError() { + return new WebServiceException(ErrorCodes.STS_INVALID_TOKEN_REQUEST); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsWSError(java.lang.Throwable) + */ + @Override + public WebServiceException stsWSError(Throwable t) { + return new WebServiceException("Security Token Service Exception", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsWSConfigurationError(java.lang.Throwable) + */ + @Override + public WebServiceException stsWSConfigurationError(Throwable t) { + return new WebServiceException(ErrorCodes.STS_CONFIGURATION_EXCEPTION, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsWSInvalidRequestTypeError(java.lang.String) + */ + @Override + public WSTrustException stsWSInvalidRequestTypeError(String requestType) { + return new WSTrustException(ErrorCodes.STS_INVALID_REQUEST_TYPE + requestType); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsWSHandlingTokenRequestError(java.lang.Throwable) + */ + @Override + public WebServiceException stsWSHandlingTokenRequestError(Throwable t) { + return new WebServiceException(ErrorCodes.STS_EXCEPTION_HANDLING_TOKEN_REQ + t.getMessage(), t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsWSResponseWritingError(java.lang.Throwable) + */ + @Override + public WebServiceException stsWSResponseWritingError(Throwable t) { + return new WebServiceException(ErrorCodes.STS_RESPONSE_WRITING_ERROR + t.getMessage(), t); + } + + @Override + public RuntimeException stsUnableToConstructKeyManagerError(Throwable t) { + return new RuntimeException(ErrorCodes.STS_UNABLE_TO_CONSTRUCT_KEYMGR, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsPublicKeyError(java.lang.String, java.lang.Throwable) + */ + @Override + public RuntimeException stsPublicKeyError(String serviceName, Throwable t) { + return new RuntimeException(ErrorCodes.STS_PUBLIC_KEY_ERROR + serviceName, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsSigningKeyPairError(java.lang.Exception) + */ + @Override + public RuntimeException stsSigningKeyPairError(Throwable t) { + return new RuntimeException(ErrorCodes.STS_SIGNING_KEYPAIR_ERROR, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsPublicKeyCertError(java.lang.Throwable) + */ + @Override + public RuntimeException stsPublicKeyCertError(Throwable t) { + return new RuntimeException(ErrorCodes.STS_PUBLIC_KEY_CERT, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#tokenTimeoutNotSpecified() + */ + @Override + public void stsTokenTimeoutNotSpecified() { + this.warn("Lifetime has not been specified. Using the default timeout value."); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsCombinedSecretKeyError(java.lang.Throwable) + */ + @Override + public WSTrustException wsTrustCombinedSecretKeyError(Throwable t) { + return new WSTrustException(ErrorCodes.STS_COMBINED_SECRET_KEY_ERROR, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsClientPublicKeyError() + */ + @Override + public WSTrustException wsTrustClientPublicKeyError() { + return new WSTrustException(ErrorCodes.STS_CLIENT_PUBLIC_KEY_ERROR); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsError(java.lang.Throwable) + */ + @Override + public WSTrustException stsError(Throwable t) { + return new WSTrustException(t.getMessage(), t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#signatureInvalidError(java.lang.String, java.lang.Throwable) + */ + @Override + public XMLSignatureException signatureInvalidError(String message, Throwable t) { + return new XMLSignatureException(ErrorCodes.INVALID_DIGITAL_SIGNATURE + message); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsSecurityTokenSignatureNotVerified() + */ + @Override + public void stsSecurityTokenSignatureNotVerified() { + this.warn("Security Token digital signature has NOT been verified. Either the STS has been configured" + + "not to sign tokens or the STS key pair has not been properly specified."); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#encryptProcessError(java.lang.Throwable) + */ + @Override + public RuntimeException encryptProcessError(Throwable t) { + return new RuntimeException(t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsSecurityTokenShouldBeEncrypted() + */ + @Override + public void stsSecurityTokenShouldBeEncrypted() { + logger.warn("Security token should be encrypted but no encrypting key could be found"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsUnableToDecodePasswordError(java.lang.String) + */ + @Override + public RuntimeException unableToDecodePasswordError(String password) { + return new RuntimeException(ErrorCodes.PROCESSING_EXCEPTION + "Unable to decode password:" + password); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#couldNotLoadProperties(java.lang.String) + */ + @Override + public IllegalStateException couldNotLoadProperties(String configFile) { + return new IllegalStateException(ErrorCodes.PROCESSING_EXCEPTION + "Could not load properties from " + configFile); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsKeyInfoTypeCreationError(java.lang.Throwable) + */ + @Override + public WSTrustException stsKeyInfoTypeCreationError(Throwable t) { + return new WSTrustException(ErrorCodes.PROCESSING_EXCEPTION + "Error creating KeyInfoType", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsSecretKeyNotEncrypted() + */ + @Override + public void stsSecretKeyNotEncrypted() { + logger.warn("Secret key could not be encrypted because the endpoint's PKC has not been specified"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authCouldNotIssueSAMLToken() + */ + @Override + public LoginException authCouldNotIssueSAMLToken() { + return new LoginException(ErrorCodes.PROCESSING_EXCEPTION + "Could not issue a SAML Security Token"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authLoginError(java.lang.Throwable) + */ + @Override + public LoginException authLoginError(Throwable t) { + LoginException loginException = new LoginException("Error during login/authentication"); + + loginException.initCause(t); + + return loginException; + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authCouldNotCreateWSTrustClient(java.lang.Throwable) + */ + @Override + public IllegalStateException authCouldNotCreateWSTrustClient(Throwable t) { + return new IllegalStateException(ErrorCodes.PROCESSING_EXCEPTION + "Could not create WSTrustClient:", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authSAMLAssertionWithoutExpiration(java.lang.String) + */ + @Override + public void samlAssertionWithoutExpiration(String id) { + logger.warn("SAML Assertion has been found to have no expiration: ID = " + id); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authCouldNotValidateSAMLToken(org.w3c.dom.Element) + */ + @Override + public LoginException authCouldNotValidateSAMLToken(Element token) { + return new LoginException(ErrorCodes.PROCESSING_EXCEPTION + "Could not validate the SAML Security Token :" + token); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authCouldNotLocateSecurityToken() + */ + @Override + public LoginException authCouldNotLocateSecurityToken() { + return new LoginException(ErrorCodes.NULL_VALUE + "Could not locate a Security Token from the callback."); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#wsTrustNullCancelTargetError() + */ + @Override + public ProcessingException wsTrustNullCancelTargetError() { + return new ProcessingException(ErrorCodes.NULL_VALUE + "Invalid cancel request: missing required CancelTarget"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#saml11MarshallError(java.lang.Throwable) + */ + @Override + public ProcessingException samlAssertionMarshallError(Throwable t) { + return new ProcessingException(ErrorCodes.PROCESSING_EXCEPTION + "Failed to marshall assertion", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#wsTrustNullRenewTargetError() + */ + @Override + public ProcessingException wsTrustNullRenewTargetError() { + return new ProcessingException(ErrorCodes.NULL_VALUE + "Invalid renew request: missing required RenewTarget"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#saml11UnmarshallError(java.lang.Throwable) + */ + @Override + public ProcessingException samlAssertionUnmarshallError(Throwable t) { + return new ProcessingException(ErrorCodes.PROCESSING_EXCEPTION + "Error unmarshalling assertion", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlAssertionRevokedCouldNotRenew() + */ + @Override + public ProcessingException samlAssertionRevokedCouldNotRenew(String id) { + return new ProcessingException(ErrorCodes.ASSERTION_RENEWAL_EXCEPTION + "SAMLV1.1 Assertion with id " + id + + " has been canceled and cannot be renewed"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#wsTrustNullValidationTargetError() + */ + @Override + public ProcessingException wsTrustNullValidationTargetError() { + return new ProcessingException(ErrorCodes.NULL_VALUE + "Bad validate request: missing required ValidateTarget"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsWrongAttributeProviderTypeNotInstalled(java.lang.String) + */ + @Override + public void stsWrongAttributeProviderTypeNotInstalled(String attributeProviderClassName) { + logger.warn("Attribute provider not installed: " + attributeProviderClassName + + "is not an instance of SAML20TokenAttributeProvider"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#stsAttributeProviderInstationError(java.lang.Throwable) + */ + @Override + public void attributeProviderInstationError(Throwable t) { + logger.warn("Error instantiating attribute provider: " + t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlAssertion(java.lang.String) + */ + @Override + public void samlAssertion(String nodeAsString) { + trace("SAML Assertion Element=" + nodeAsString); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#wsTrustUnableToGetDataTypeFactory(javax.xml.datatype. + *DatatypeConfigurationException) + */ + @Override + public RuntimeException wsTrustUnableToGetDataTypeFactory(Throwable t) { + return new RuntimeException(ErrorCodes.PROCESSING_EXCEPTION + "Unable to get DatatypeFactory instance", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#wsTrustValidationStatusCodeMissing() + */ + @Override + public ProcessingException wsTrustValidationStatusCodeMissing() { + return new ProcessingException(ErrorCodes.NULL_VALUE + "Validation status code is missing"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#identityServerActiveSessionCount(int) + */ + @Override + public void samlIdentityServerActiveSessionCount(int activeSessionCount) { + info("Active Session Count=" + activeSessionCount); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#identityServerSessionCreated(java.lang.String, int) + */ + @Override + public void samlIdentityServerSessionCreated(String id, int activeSessionCount) { + trace("Session Created with id=" + id + "::active session count=" + activeSessionCount); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#identityServerSessionDestroyed(java.lang.String, int) + */ + @Override + public void samlIdentityServerSessionDestroyed(String id, int activeSessionCount) { + trace("Session Destroyed with id=" + id + "::active session count=" + activeSessionCount); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#unknowCredentialType(java.lang.String) + */ + @Override + public RuntimeException unknowCredentialType(String name) { + return new RuntimeException(ErrorCodes.UNSUPPORTED_TYPE + "Unknown credential type:" + name); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerRoleGeneratorSetupError(java.lang.Throwable) + */ + @Override + public void samlHandlerRoleGeneratorSetupError(Throwable t) { + logger.error("Exception initializing role generator:", t); + } + + @Override + public RuntimeException samlHandlerAssertionNotFound() { + return new RuntimeException(ErrorCodes.NULL_VALUE + "Assertion not found in the handler request"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerAuthnRequestIsNull() + */ + @Override + public ProcessingException samlHandlerAuthnRequestIsNull() { + return new ProcessingException(ErrorCodes.NULL_VALUE + "AuthnRequest is null"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerAuthenticationError(java.lang.Throwable) + */ + @Override + public void samlHandlerAuthenticationError(Throwable t) { + logger.error("Exception in processing authentication:", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerNoAssertionFromIDP() + */ + @Override + public IllegalArgumentException samlHandlerNoAssertionFromIDP() { + return new IllegalArgumentException(ErrorCodes.NULL_VALUE + "No assertions in reply from IDP"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerNullEncryptedAssertion() + */ + @Override + public ProcessingException samlHandlerNullEncryptedAssertion() { + return new ProcessingException(ErrorCodes.NULL_VALUE + "Null encrypted assertion element"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerIDPAuthenticationFailedError() + */ + @Override + public SecurityException samlHandlerIDPAuthenticationFailedError() { + return new SecurityException(ErrorCodes.IDP_AUTH_FAILED + "IDP forbid the user"); + } + + /* + *(non-Javadoc) + * + *@see + *org.picketlink.identity.federation.PicketLinkLogger#assertionExpiredError(org.picketlink.identity.federation.core.saml + *.v2.exceptions.AssertionExpiredException) + */ + @Override + public ProcessingException assertionExpiredError(AssertionExpiredException aee) { + return new ProcessingException(ErrorCodes.EXPIRED_ASSERTION + "Assertion has expired", aee); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#unsupportedRoleType(java.lang.Object) + */ + @Override + public RuntimeException unsupportedRoleType(Object attrValue) { + return new RuntimeException(ErrorCodes.UNSUPPORTED_TYPE + "Unknown role object type : " + attrValue); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerFailedInResponseToVerification(java.lang.String, + *java.lang.String) + */ + @Override + public void samlHandlerFailedInResponseToVerification(String inResponseTo, String authnRequestId) { + trace("Verification of InResponseTo failed. InResponseTo from SAML response is " + inResponseTo + + ". Value of request Id from HTTP session is " + authnRequestId); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerFailedInResponseToVerificarionError() + */ + @Override + public ProcessingException samlHandlerFailedInResponseToVerificarionError() { + return new ProcessingException(ErrorCodes.AUTHN_REQUEST_ID_VERIFICATION_FAILED); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerIssuerNotTrustedError(java.lang.String) + */ + @Override + public IssuerNotTrustedException samlIssuerNotTrustedError(String issuer) { + return new IssuerNotTrustedException("Issuer not Trusted: " + issuer); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerIssuerNotTrustedError(java.lang.Throwable) + */ + @Override + public IssuerNotTrustedException samlIssuerNotTrustedException(Throwable t) { + return new IssuerNotTrustedException(t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerTrustElementMissingError() + */ + @Override + public ConfigurationException samlHandlerTrustElementMissingError() { + return new ConfigurationException(ErrorCodes.NULL_VALUE + "trust element missing"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerIdentityServerNotFound() + */ + @Override + public ProcessingException samlHandlerIdentityServerNotFoundError() { + return new ProcessingException(ErrorCodes.NULL_VALUE + "Identity Server not found"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerPrincipalNotFoundError() + */ + @Override + public ProcessingException samlHandlerPrincipalNotFoundError() { + return new ProcessingException(ErrorCodes.PRINCIPAL_NOT_FOUND); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerKeyPairNotFound() + */ + @Override + public void samlHandlerKeyPairNotFound() { + trace("Key Pair cannot be found"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerKeyPairNotFoundError() + */ + @Override + public ProcessingException samlHandlerKeyPairNotFoundError() { + return new ProcessingException("Key Pair cannot be found"); + } + + /* + *(non-Javadoc) + * + *@see + *org.picketlink.identity.federation.PicketLinkLogger#samlHandlerErrorSigningRedirectBindingMessage(java.lang.Throwable) + */ + @Override + public void samlHandlerErrorSigningRedirectBindingMessage(Throwable t) { + logger.error("Error when trying to sign message for redirection", t); + } + + /* + *(non-Javadoc) + * + *@see + *org.picketlink.identity.federation.PicketLinkLogger#samlHandlerSigningRedirectBindingMessageError(org.picketlink.identity + *.federation.core.exceptions.ConfigurationException) + */ + @Override + public RuntimeException samlHandlerSigningRedirectBindingMessageError(Throwable t) { + return new RuntimeException(t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#signatureValidationError() + */ + @Override + public SignatureValidationException samlHandlerSignatureValidationFailed() { + return new SignatureValidationException(ErrorCodes.INVALID_DIGITAL_SIGNATURE + "Signature Validation Failed"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerErrorValidatingSignature(java.lang.Throwable) + */ + @Override + public void samlHandlerErrorValidatingSignature(Throwable t) { + logger.error("Error validating signature:", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerInvalidSignatureError() + */ + @Override + public ProcessingException samlHandlerInvalidSignatureError() { + return new ProcessingException(ErrorCodes.INVALID_DIGITAL_SIGNATURE + "Error validating signature."); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerSignatureNorPresentError() + */ + @Override + public ProcessingException samlHandlerSignatureNotPresentError() { + return new ProcessingException(ErrorCodes.INVALID_DIGITAL_SIGNATURE + + "Signature Validation failed. Signature is not present. Check if the IDP is supporting signatures."); + } + + @Override + public ProcessingException samlHandlerSignatureValidationError(Throwable t) { + return new ProcessingException(ErrorCodes.INVALID_DIGITAL_SIGNATURE + "Signature Validation failed", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerChainProcessingError(java.lang.Throwable) + */ + @Override + public RuntimeException samlHandlerChainProcessingError(Throwable t) { + return new RuntimeException("Error during processing the SAML Handler Chain.", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#trustKeyManagerMissing() + */ + @Override + public TrustKeyConfigurationException trustKeyManagerMissing() { + return new TrustKeyConfigurationException(ErrorCodes.TRUST_MANAGER_MISSING); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlBase64DecodingError(java.lang.Throwable) + */ + @Override + public void samlBase64DecodingError(Throwable t) { + logger.error("Error in base64 decoding saml message.", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlParsingError(java.lang.Throwable) + */ + @Override + public void samlParsingError(Throwable t) { + logger.error("Exception in parsing saml message:", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#attributeManagerMappingContextNull() + */ + @Override + public void mappingContextNull() { + logger.error("Mapping Context returned is null"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#attributeManagerError(java.lang.Throwable) + */ + @Override + public void attributeManagerError(Throwable t) { + logger.error("Exception in attribute mapping:", t); + } + + @Override + public void couldNotObtainSecurityContext() { + logger.error("Could not obtain security context."); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authFailedToCreatePrincipal(java.lang.Throwable) + */ + @Override + public LoginException authFailedToCreatePrincipal(Throwable t) { + LoginException loginException = new LoginException(ErrorCodes.PROCESSING_EXCEPTION + "Failed to create principal: " + + t.getMessage()); + + loginException.initCause(t); + + return loginException; + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authSharedCredentialIsNotSAMLCredential() + */ + @Override + public LoginException authSharedCredentialIsNotSAMLCredential(String className) { + return new LoginException(ErrorCodes.WRONG_TYPE + + "SAML2STSLoginModule: Shared credential is not a SAML credential. Got " + className); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authSTSConfigFileNotFound() + */ + @Override + public LoginException authSTSConfigFileNotFound() { + return new LoginException(ErrorCodes.SAML2STSLM_CONF_FILE_MISSING); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authErrorHandlingCallback(java.lang.Throwable) + */ + @Override + public LoginException authErrorHandlingCallback(Throwable t) { + LoginException loginException = new LoginException("Error handling callback."); + + loginException.initCause(t); + + return loginException; + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authInvalidSAMLAssertionBySTS() + */ + @Override + public LoginException authInvalidSAMLAssertionBySTS() { + return new LoginException(ErrorCodes.INVALID_ASSERTION + + "SAML2STSLoginModule: Supplied assertion was considered invalid by the STS"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authAssertionValidationValies(java.lang.Throwable) + */ + @Override + public LoginException authAssertionValidationError(Throwable t) { + LoginException loginException = new LoginException("Failed to validate assertion using STS"); + + loginException.initCause(t); + + return loginException; + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authFailedToParseSAMLAssertion(java.lang.Throwable) + */ + @Override + public LoginException authFailedToParseSAMLAssertion(Throwable t) { + LoginException exception = new LoginException("PL00044: SAML2STSLoginModule: Failed to parse assertion element:" + + t.getMessage()); + exception.initCause(t); + return exception; + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authSAMLAssertionPasingFailed(java.lang.Throwable) + */ + @Override + public void samlAssertionPasingFailed(Throwable t) { + logger.error("SAML Assertion parsing failed", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authNullKeyStoreFromSecurityDomainError(java.lang.String) + */ + @Override + public LoginException authNullKeyStoreFromSecurityDomainError(String name) { + return new LoginException(ErrorCodes.NULL_VALUE + "SAML2STSLoginModule: null truststore for " + name); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authNullKeyStoreAliasFromSecurityDomain(java.lang.String) + */ + @Override + public LoginException authNullKeyStoreAliasFromSecurityDomainError(String name) { + return new LoginException(ErrorCodes.NULL_VALUE + "SAML2STSLoginModule: null KeyStoreAlias for " + name + + "; set 'KeyStoreAlias' in '" + name + "' security domain configuration"); + } + + @Override + public LoginException authNoCertificateFoundForAliasError(String alias, String name) { + return new LoginException(ErrorCodes.NULL_VALUE + "No certificate found for alias '" + alias + "' in the '" + name + + "' security domain"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authSAMLInvalidSignature() + */ + @Override + public LoginException authSAMLInvalidSignatureError() { + return new LoginException(ErrorCodes.INVALID_DIGITAL_SIGNATURE + "SAML2STSLoginModule: " + + WSTrustConstants.STATUS_CODE_INVALID + " : invalid SAML V2.0 assertion signature"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authSAMLAssertionExpiredError() + */ + @Override + public LoginException authSAMLAssertionExpiredError() { + return new LoginException(ErrorCodes.EXPIRED_ASSERTION + "SAML2STSLoginModule: " + WSTrustConstants.STATUS_CODE_INVALID + + "::assertion expired or used before its lifetime period"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authSAMLAssertionIssuingFailed(java.lang.Throwable) + */ + @Override + public void authSAMLAssertionIssuingFailed(Throwable t) { + logger.error("Unable to issue assertion", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#jbossWSUnableToCreateBinaryToken(java.lang.Throwable) + */ + @Override + public void jbossWSUnableToCreateBinaryToken(Throwable t) { + logger.error("Unable to create binary token", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#jbossWSUnableToCreateSecurityToken() + */ + @Override + public void jbossWSUnableToCreateSecurityToken() { + logger.warn("Was not able to create security token. Just sending message without binary token"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#jbossWSUnableToWriteSOAPMessage(java.lang.Exception) + */ + @Override + public void jbossWSUnableToWriteSOAPMessage(Throwable t) { + logger.error("Exception writing SOAP Message", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#jbossWSUnableToLoadJBossWSSEConfigError() + */ + @Override + public RuntimeException jbossWSUnableToLoadJBossWSSEConfigError() { + return new RuntimeException(ErrorCodes.RESOURCE_NOT_FOUND + "unable to load jboss-wsse.xml"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#jbossWSAuthorizationFailed() + */ + @Override + public RuntimeException jbossWSAuthorizationFailed() { + return new RuntimeException(ErrorCodes.PROCESSING_EXCEPTION + "Authorization Failed"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#jbossWSErrorGettingOperationName(java.lang.Throwable) + */ + @Override + public void jbossWSErrorGettingOperationName(Throwable t) { + logger.error("Exception using backup method to get op name=", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authSAMLCredentialNotAvailable() + */ + @Override + public LoginException authSAMLCredentialNotAvailable() { + return new LoginException(ErrorCodes.NULL_VALUE + "SamlCredential is not available in subject"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#unableToInstantiateHandler(java.lang.String, + *java.lang.Throwable) + */ + @Override + public RuntimeException authUnableToInstantiateHandler(String token, Throwable t) { + return new RuntimeException(ErrorCodes.CANNOT_CREATE_INSTANCE + "Unable to instantiate handler:" + token, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#jbossWSUnableToCreateSSLSocketFactory(java.lang.Throwable) + */ + @Override + public RuntimeException jbossWSUnableToCreateSSLSocketFactory(Throwable t) { + return new RuntimeException(ErrorCodes.PROCESSING_EXCEPTION + "Unable to create SSL Socket Factory:", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#jbossWSUnableToFindSSLSocketFactory() + */ + @Override + public RuntimeException jbossWSUnableToFindSSLSocketFactory() { + return new RuntimeException("We did not find SSL Socket Factory"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authUnableToGetIdentityFromSubject() + */ + @Override + public RuntimeException authUnableToGetIdentityFromSubject() { + return new RuntimeException(ErrorCodes.PROCESSING_EXCEPTION + "Unable to get the Identity from the subject."); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#authSAMLAssertionNullOrEmpty() + */ + @Override + public RuntimeException authSAMLAssertionNullOrEmpty() { + return new RuntimeException("SAML Assertion is null or empty"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#jbossWSUncheckedAndRolesCannotBeTogether() + */ + @Override + public ProcessingException jbossWSUncheckedAndRolesCannotBeTogether() { + return new ProcessingException(ErrorCodes.PROCESSING_EXCEPTION + "unchecked and role(s) cannot be together"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlIDPHandlingSAML11Error(java.lang.Throwable) + */ + @Override + public void samlIDPHandlingSAML11Error(Throwable t) { + logger.error("Exception handling saml 11 use case:", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlIDPValidationCheckFailed() + */ + @Override + public GeneralSecurityException samlIDPValidationCheckFailed() { + return new GeneralSecurityException(ErrorCodes.VALIDATION_CHECK_FAILED); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlIDPRequestProcessingError(java.lang.Throwable) + */ + @Override + public void samlIDPRequestProcessingError(Throwable t) { + logger.error("Exception in processing request:", t); + } + + /* + *(non-Javadoc) + * + *@see + *org.picketlink.identity.federation.PicketLinkLogger#samlIDPUnableToSetParticipantStackUsingDefault(java.lang.Throwable) + */ + @Override + public void samlIDPUnableToSetParticipantStackUsingDefault(Throwable t) { + logger.warn("Unable to set the Identity Participant Stack Class. Will just use the default"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerConfigurationError(java.lang.Throwable) + */ + @Override + public void samlHandlerConfigurationError(Throwable t) { + logger.error("Exception dealing with handler configuration:", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlIDPSettingCanonicalizationMethod(java.lang.String) + */ + @Override + public void samlIDPSettingCanonicalizationMethod(String canonicalizationMethod) { + logger.debug("Setting the CanonicalizationMethod on XMLSignatureUtil::" + canonicalizationMethod); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlIDPConfigurationError(java.lang.Throwable) + */ + @Override + public RuntimeException samlIDPConfigurationError(Throwable t) { + return new RuntimeException(ErrorCodes.PROCESSING_EXCEPTION + t.getMessage(), t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#configurationFileMissing(java.lang.String) + */ + @Override + public RuntimeException configurationFileMissing(String configFile) { + return new RuntimeException(ErrorCodes.IDP_WEBBROWSER_VALVE_CONF_FILE_MISSING + configFile); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlIDPInstallingDefaultSTSConfig() + */ + @Override + public void samlIDPInstallingDefaultSTSConfig() { + logger.info("Did not find picketlink-sts.xml. We will install default configuration"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#warn(java.lang.String) + */ + @Override + public void warn(String message) { + logger.warn(message); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlSPFallingBackToLocalFormAuthentication() + */ + @Override + public void samlSPFallingBackToLocalFormAuthentication() { + logger.error("Falling back on local Form Authentication if available"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#unableLocalAuthentication(java.lang.Throwable) + */ + @Override + public IOException unableLocalAuthentication(Throwable t) { + return new IOException(ErrorCodes.UNABLE_LOCAL_AUTH, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlSPUnableToGetIDPDescriptorFromMetadata() + */ + @Override + public void samlSPUnableToGetIDPDescriptorFromMetadata() { + logger.error("Unable to obtain the IDP SSO Descriptor from metadata"); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlSPConfigurationError(java.lang.Throwable) + */ + @Override + public RuntimeException samlSPConfigurationError(Throwable t) { + return new RuntimeException(t.getMessage(), t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlSPSettingCanonicalizationMethod(java.lang.String) + */ + @Override + public void samlSPSettingCanonicalizationMethod(String canonicalizationMethod) { + logger.info("Service Provider is setting the CanonicalizationMethod on XMLSignatureUtil::" + canonicalizationMethod); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlSPCouldNotDispatchToLogoutPage(java.lang.String) + */ + @Override + public void samlSPCouldNotDispatchToLogoutPage(String logOutPage) { + logger.errorf("Cannot dispatch to the logout page: no request dispatcher" + logOutPage); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#usingLoggerImplementation(java.lang.String) + */ + @Override + public void usingLoggerImplementation(String className) { + logger.debugf("Using logger implementation: " + className); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlResponseFromIDPParsingFailed() + */ + @Override + public void samlResponseFromIDPParsingFailed() { + logger.error("Error parsing the response from the IDP. Check the strict post binding configuration on both IDP and SP side."); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#auditSecurityDomainNotFound(java.lang.Throwable) + */ + @Override + public ConfigurationException auditSecurityDomainNotFound(Throwable t) { + return new ConfigurationException( + "Could not find a security domain configuration. Check if it is defined in WEB-INF/jboss-web.xml or set the " + + GeneralConstants.AUDIT_SECURITY_DOMAIN + " system property.", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#auditAuditManagerNotFound(java.lang.String, java.lang.Throwable) + */ + @Override + public ConfigurationException auditAuditManagerNotFound(String location, Throwable t) { + return new ConfigurationException("Could not find a audit manager configuration. Location: " + location, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlIssueInstantMissingError() + */ + @Override + public IssueInstantMissingException samlIssueInstantMissingError() { + return new IssueInstantMissingException(ErrorCodes.NULL_ISSUE_INSTANT); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlSPResponseNotCatalinaResponse() + */ + @Override + public RuntimeException samlSPResponseNotCatalinaResponseError(Object response) { + return new RuntimeException(ErrorCodes.SERVICE_PROVIDER_NOT_CATALINA_RESPONSE + ". Received: " + response); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlLogoutError(java.lang.Throwable) + */ + @Override + public void samlLogoutError(Throwable t) { + logger.error("Error during the logout.", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlErrorPageForwardError(java.lang.String, java.lang.Throwable) + */ + @Override + public void samlErrorPageForwardError(String errorPage, Throwable t) { + logger.error("Error forwarding to the error page: " + errorPage); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlSPHandleRequestError(java.lang.Throwable) + */ + @Override + public void samlSPHandleRequestError(Throwable t) { + logger.error("Service Provider could not handle the request.", t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlSPProcessingExceptionError() + */ + @Override + public IOException samlSPProcessingExceptionError(Throwable t) { + return new IOException(ErrorCodes.SERVICE_PROVIDER_SERVER_EXCEPTION, t); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlInvalidProtocolBinding() + */ + @Override + public IllegalArgumentException samlInvalidProtocolBinding() { + return new IllegalArgumentException("Invalid SAML Protocol Binding. Expected POST or REDIRECT."); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlHandlerServiceProviderConfigNotFound() + */ + @Override + public IllegalStateException samlHandlerServiceProviderConfigNotFound() { + return new IllegalStateException("Service Provider configuration not found. Check if the " + + GeneralConstants.CONFIGURATION + " parameter is defined in the handler chain config."); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlSecurityTokenAlreadyPersisted(java.lang.String) + */ + @Override + public void samlSecurityTokenAlreadyPersisted(String id) { + warn("Security Token with id=" + id + " has already been persisted."); + } + + /* + *(non-Javadoc) + * + *@see org.picketlink.identity.federation.PicketLinkLogger#samlSecurityTokenNotFoundInRegistry(java.lang.String) + */ + @Override + public void samlSecurityTokenNotFoundInRegistry(String id) { + warn("Security Token with id=" + id + " was not found in the registry."); + } + + /*(non-Javadoc) + *@see org.picketlink.identity.federation.PicketLinkLogger#samlMetaDataFailedToCreateCacheDuration(java.lang.String) + */ + @Override + public IllegalArgumentException samlMetaDataFailedToCreateCacheDuration(String timeValue) { + return new IllegalArgumentException("Cache duration could not be created using '" + timeValue + + "'. This value must be an ISO-8601 period or a numeric value representing the duration in milliseconds."); + } + + @Override + public ConfigurationException samlMetaDataNoIdentityProviderDefined() { + return new ConfigurationException("No configuration provided for the Identity Provider."); + } + + @Override + public ConfigurationException samlMetaDataNoServiceProviderDefined() { + return new ConfigurationException("No configuration provided for the Service Provider."); + } + + /*(non-Javadoc) + *@see org.picketlink.identity.federation.PicketLinkLogger#securityDomainNotFound() + */ + @Override + public ConfigurationException securityDomainNotFound() { + return new ConfigurationException("The security domain name could not be found. Check your jboss-web.xml."); + } + + /*(non-Javadoc) + *@see org.picketlink.identity.federation.PicketLinkLogger#authenticationManagerError(org.picketlink.identity.federation.core.exceptions.ConfigurationException) + */ + @Override + public void authenticationManagerError(ConfigurationException e) { + error("Error loading the AuthenticationManager.", e); + } + + private void error(String msg, ConfigurationException e) { + logger.error(msg, e); + } + + /*(non-Javadoc) + *@see org.picketlink.identity.federation.PicketLinkLogger#authorizationManagerError(org.picketlink.identity.federation.core.exceptions.ConfigurationException) + */ + @Override + public void authorizationManagerError(ConfigurationException e) { + error("Error loading AuthorizationManager.", e); + } + + public IllegalStateException jbdcInitializationError(Throwable throwable) { + return new IllegalStateException(throwable); + } + + public RuntimeException errorUnmarshallingToken(Throwable e) { + return new RuntimeException(e); + } + + public RuntimeException runtimeException(String msg, Throwable e) { + return new RuntimeException(msg, e); + } + + public IllegalStateException datasourceIsNull() { + return new IllegalStateException(); + } + + @Override + public IllegalArgumentException cannotParseParameterValue(String parameter, Throwable e) { + return new IllegalArgumentException("Cannot parse: " + parameter, e); + } + + @Override + public RuntimeException cannotGetFreeClientPoolKey(String key) { + return new RuntimeException("Cannot get free client pool key: " + key); + } + + @Override + public RuntimeException cannotGetSTSConfigByKey(String key) { + return new RuntimeException("Cannot get STS config by key: " + key + ". The pool for given key has to be initialized first by calling STSClientPool.initialize method."); + } + + @Override + public RuntimeException cannotGetUsedClientsByKey(String key) { + return new RuntimeException("Cannot get used clients by key: " + key); + } + + @Override + public RuntimeException removingNonExistingClientFromUsedClientsByKey(String key) { + return new RuntimeException("removing non existing client from used clients by key: " + key); + } + + @Override + public RuntimeException freePoolAlreadyContainsGivenKey(String key) { + return new RuntimeException("Free pool already contains given key: " + key); + } + + @Override + public RuntimeException maximumNumberOfClientsReachedforPool(String max) { + return new RuntimeException("Pool reached maximum number of clients within the pool (" + max + ")"); + } + + @Override + public RuntimeException cannotSetMaxPoolSizeToNegative(String max) { + return new RuntimeException("Cannot set maximum STS client pool size to negative number (" + max + ")"); + } + + @Override + public RuntimeException parserFeatureNotSupported(String feature) { + return new RuntimeException("Parser feature " + feature + " not supported."); + } + + @Override + public ProcessingException samlAssertionWrongAudience(String serviceURL) { + return new ProcessingException("Wrong audience [" + serviceURL + "]."); + } + + @Override + public ProcessingException samlExtensionUnknownChild(Class clazz) { + return new ProcessingException("Unknown child type specified for extension: " + + (clazz == null ? "" : clazz.getSimpleName()) + + "."); + } +} diff --git a/src/main/java/nl/first8/keycloak/saml/common/PicketLinkLoggerFactory.java b/src/main/java/nl/first8/keycloak/saml/common/PicketLinkLoggerFactory.java new file mode 100644 index 0000000..f3ae78c --- /dev/null +++ b/src/main/java/nl/first8/keycloak/saml/common/PicketLinkLoggerFactory.java @@ -0,0 +1,10 @@ +package nl.first8.keycloak.saml.common; + +import org.jboss.logging.Logger; +import org.keycloak.saml.common.PicketLinkLogger; + +public class PicketLinkLoggerFactory { + public static PicketLinkLogger getLogger(Logger logger) { + return new DefaultPicketLinkLogger(logger); + } +} diff --git a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java index ef8ac89..92e2bf7 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java @@ -14,7 +14,8 @@ import org.keycloak.dom.saml.v2.assertion.NameIDType; import org.keycloak.dom.saml.v2.protocol.*; import org.keycloak.saml.common.PicketLinkLogger; -import org.keycloak.saml.common.PicketLinkLoggerFactory; +import nl.first8.keycloak.saml.common.PicketLinkLoggerFactory; +import org.jboss.logging.Logger; import org.keycloak.saml.common.constants.GeneralConstants; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ConfigurationException; @@ -38,7 +39,7 @@ */ public class SAML2Request { - private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); + private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(Logger.getLogger(SAML2Request.class)); private SAMLDocumentHolder samlDocumentHolder = null; private String nameIDFormat = JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get(); @@ -118,7 +119,7 @@ public AuthnRequestType createAuthnRequestType(String id, String assertionConsum * is null */ public AuthnRequestType getAuthnRequestType(String fileName) throws ConfigurationException, ProcessingException, - ParsingException { + ParsingException { if (fileName == null) throw logger.nullArgumentError("fileName"); URL resourceURL = SecurityActions.loadResource(getClass(), fileName); @@ -143,7 +144,7 @@ public AuthnRequestType getAuthnRequestType(String fileName) throws Configuratio * @throws ParsingException */ public static SAMLDocumentHolder getSAML2ObjectFromStream(InputStream is) throws ConfigurationException, ParsingException, - ProcessingException { + ProcessingException { if (is == null) throw logger.nullArgumentError("InputStream"); @@ -178,7 +179,7 @@ public static SAMLDocumentHolder getSAML2ObjectFromDocument(Document samlDocumen * @throws IllegalArgumentException inputstream is null */ public RequestAbstractType getRequestType(InputStream is) throws ParsingException, ConfigurationException, - ProcessingException { + ProcessingException { if (is == null) throw logger.nullArgumentError("InputStream"); @@ -203,7 +204,7 @@ public RequestAbstractType getRequestType(InputStream is) throws ParsingExceptio * @throws IllegalArgumentException inputstream is null */ public AuthnRequestType getAuthnRequestType(InputStream is) throws ConfigurationException, ProcessingException, - ParsingException { + ParsingException { if (is == null) throw logger.nullArgumentError("InputStream"); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java index f1158d8..e20f0e7 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java @@ -7,7 +7,8 @@ import org.keycloak.dom.saml.v2.protocol.ResponseType; import org.keycloak.dom.saml.v2.protocol.StatusResponseType; import org.keycloak.saml.common.PicketLinkLogger; -import org.keycloak.saml.common.PicketLinkLoggerFactory; +import nl.first8.keycloak.saml.common.PicketLinkLoggerFactory; +import org.jboss.logging.Logger; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ParsingException; @@ -42,7 +43,7 @@ public class SAML2Response { - private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); + private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(Logger.getLogger(SAML2Response.class)); private final long ASSERTION_VALIDITY = 5000; // 5secs in milis private final long CLOCK_SKEW = 2000; // 2secs @@ -122,7 +123,7 @@ public AuthzDecisionStatementType createAuthzDecisionStatementType(String resour * @throws ProcessingException */ public ResponseType createResponseType(String ID, SPInfoHolder sp, IDPInfoHolder idp, IssuerInfoHolder issuerInfo) - throws ProcessingException { + throws ProcessingException { String responseDestinationURI = sp.getResponseDestinationURI(); XMLGregorianCalendar issueInstant = XMLTimeUtil.getIssueInstant(); @@ -162,7 +163,7 @@ public ResponseType createResponseType(String ID, SPInfoHolder sp, IDPInfoHolder String assertionID = IDGenerator.create("ID_"); assertionType = SAMLAssertionFactory.createAssertion(assertionID, issuerID, issueInstant, conditions, - subjectType, statements); + subjectType, statements); try { AssertionUtil.createTimedConditions(assertionType, ASSERTION_VALIDITY, CLOCK_SKEW); @@ -213,7 +214,7 @@ public ResponseType createResponseType(String ID, IssuerInfoHolder issuerInfo, A * @throws ConfigurationException */ public ResponseType createResponseType(String ID, IssuerInfoHolder issuerInfo, Element encryptedAssertion) - throws ConfigurationException { + throws ConfigurationException { return JBossSAMLAuthnResponseFactory.createResponseType(ID, issuerInfo, encryptedAssertion); } @@ -226,7 +227,7 @@ public ResponseType createResponseType(String ID, IssuerInfoHolder issuerInfo, E * @throws IssueInstantMissingException */ public void createTimedConditions(AssertionType assertion, long durationInMilis) throws ConfigurationException, - IssueInstantMissingException { + IssueInstantMissingException { AssertionUtil.createTimedConditions(assertion, durationInMilis); } @@ -240,7 +241,7 @@ public void createTimedConditions(AssertionType assertion, long durationInMilis) * @throws ConfigurationException */ public EncryptedAssertionType getEncryptedAssertion(InputStream is) throws ParsingException, ConfigurationException, - ProcessingException { + ProcessingException { if (is == null) throw logger.nullArgumentError("InputStream"); @@ -313,7 +314,7 @@ public ResponseType getResponseType(InputStream is) throws ParsingException, Con * @throws ProcessingException */ public SAML2Object getSAML2ObjectFromStream(InputStream is) throws ParsingException, ConfigurationException, - ProcessingException { + ProcessingException { if (is == null) throw logger.nullArgumentError("InputStream"); @@ -376,7 +377,7 @@ public Document convert(EncryptedElementType encryptedElementType) throws Config * @throws ProcessingException */ public static Document convert(StatusResponseType responseType) throws ProcessingException, ConfigurationException, - ParsingException { + ParsingException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); SAMLResponseWriter writer = new SAMLResponseWriter(StaxUtil.getXMLStreamWriter(bos)); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java index 47e9a86..aa0a9fd 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java @@ -2,7 +2,8 @@ import nl.first8.keycloak.saml.processing.core.util.XMLSignatureUtil; import org.keycloak.saml.common.PicketLinkLogger; -import org.keycloak.saml.common.PicketLinkLoggerFactory; +import nl.first8.keycloak.saml.common.PicketLinkLoggerFactory; +import org.jboss.logging.Logger; import org.keycloak.saml.common.constants.JBossSAMLConstants; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ProcessingException; @@ -24,7 +25,7 @@ public class SAML2Signature { - private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); + private static final PicketLinkLogger picketLogger = PicketLinkLoggerFactory.getLogger(Logger.getLogger(SAML2Signature.class)); private String signatureMethod = SignatureMethod.RSA_SHA1; @@ -97,7 +98,7 @@ public void setX509Certificate(X509Certificate x509Certificate) { * @throws GeneralSecurityException */ public Document sign(Document doc, String referenceID, String keyName, KeyPair keyPair, String canonicalizationMethodType) throws ParserConfigurationException, - GeneralSecurityException, MarshalException, XMLSignatureException { + GeneralSecurityException, MarshalException, XMLSignatureException { String referenceURI = "#" + referenceID; configureIdAttribute(doc); @@ -132,7 +133,7 @@ public void signSAMLDocument(Document samlDocument, String keyName, KeyPair keyp try { sign(samlDocument, id, keyName, keypair, canonicalizationMethodType); } catch (ParserConfigurationException | GeneralSecurityException | MarshalException | XMLSignatureException e) { - throw new ProcessingException(logger.signatureError(e)); + throw new ProcessingException(picketLogger.signatureError(e)); } } @@ -147,16 +148,11 @@ public void signSAMLDocument(Document samlDocument, String keyName, KeyPair keyp * @throws ProcessingException */ public boolean validate(Document signedDocument, KeyLocator keyLocator) throws ProcessingException { - logger.warn("Called without configuration for Saml Advice Nodes: defaulting to false."); - return validate(signedDocument, keyLocator, false); - } - - public boolean validate(Document signedDocument, KeyLocator keyLocator, boolean ignoreSamlAdviceNodes) throws ProcessingException { try { configureIdAttribute(signedDocument); - return XMLSignatureUtil.validate(signedDocument, keyLocator, ignoreSamlAdviceNodes); + return XMLSignatureUtil.validate(signedDocument, keyLocator); } catch (MarshalException | XMLSignatureException me) { - throw new ProcessingException(logger.signatureError(me)); + throw new ProcessingException(picketLogger.signatureError(me)); } } @@ -188,11 +184,12 @@ public Node getNextSiblingOfIssuer(Document doc) { * @param document SAML document to have its ID attribute configured. */ public static void configureIdAttribute(Document document) { + picketLogger.trace("configureIdAttribute() begin"); // Estabilish the IDness of the ID attribute. configureIdAttribute(document.getDocumentElement()); NodeList nodes = document.getElementsByTagNameNS(JBossSAMLURIConstants.ASSERTION_NSURI.get(), - JBossSAMLConstants.ASSERTION.get()); + JBossSAMLConstants.ASSERTION.get()); for (int i = 0; i < nodes.getLength(); i++) { configureIdAttribute((Element) nodes.item(i)); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeValueParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeValueParser.java index 52ef7b6..1a1558c 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeValueParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeValueParser.java @@ -9,7 +9,8 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.Namespace; import org.keycloak.saml.common.PicketLinkLogger; -import org.keycloak.saml.common.PicketLinkLoggerFactory; +import nl.first8.keycloak.saml.common.PicketLinkLoggerFactory; +import org.jboss.logging.Logger; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.parsers.StaxParser; @@ -30,7 +31,7 @@ public class SAMLAttributeValueParser implements StaxParser { - private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); + private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(Logger.getLogger(SAMLAttributeValueParser.class)); private static final SAMLAttributeValueParser INSTANCE = new SAMLAttributeValueParser(); private static final QName NIL = new QName(JBossSAMLURIConstants.XSI_NSURI.get(), "nil", JBossSAMLURIConstants.XSI_PREFIX.get()); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/xmlsec/CipherValueParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/xmlsec/CipherValueParser.java index 06f4e85..91e9200 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/xmlsec/CipherValueParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/xmlsec/CipherValueParser.java @@ -2,7 +2,8 @@ import nl.first8.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionQNames; import org.keycloak.saml.common.PicketLinkLogger; -import org.keycloak.saml.common.PicketLinkLoggerFactory; +import nl.first8.keycloak.saml.common.PicketLinkLoggerFactory; +import org.jboss.logging.Logger; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.parsers.StaxParser; @@ -19,7 +20,7 @@ */ public class CipherValueParser implements StaxParser { - private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); + private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(Logger.getLogger(CipherValueParser.class)); private static final CipherValueParser INSTANCE = new CipherValueParser(); private static final QName NIL = new QName(JBossSAMLURIConstants.XSI_NSURI.get(), "nil", JBossSAMLURIConstants.XSI_PREFIX.get()); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java index eccc621..6615ee1 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java @@ -24,7 +24,8 @@ import org.keycloak.dom.saml.v2.protocol.StatusCodeType; import org.keycloak.dom.saml.v2.protocol.StatusType; import org.keycloak.saml.common.PicketLinkLogger; -import org.keycloak.saml.common.PicketLinkLoggerFactory; +import nl.first8.keycloak.saml.common.PicketLinkLoggerFactory; +import org.jboss.logging.Logger; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.processing.core.saml.v2.holders.IssuerInfoHolder; @@ -42,7 +43,7 @@ */ public class JBossSAMLAuthnResponseFactory { - private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); + private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(Logger.getLogger(JBossSAMLAuthnResponseFactory.class)); /** * Create a StatusType given the status code uri diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java index f90d395..2dd8530 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java @@ -34,7 +34,8 @@ import org.keycloak.rotation.KeyLocator; import org.keycloak.saml.common.ErrorCodes; import org.keycloak.saml.common.PicketLinkLogger; -import org.keycloak.saml.common.PicketLinkLoggerFactory; +import nl.first8.keycloak.saml.common.PicketLinkLoggerFactory; +import org.jboss.logging.Logger; import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ProcessingException; @@ -66,7 +67,7 @@ public class AssertionUtil { - private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); + private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(Logger.getLogger(AssertionUtil.class)); /** * Given {@code AssertionType}, convert it into a String @@ -189,7 +190,7 @@ public static AttributeType createAttribute(String name, String nameFormat, Obje *

*/ public static void createTimedConditions(AssertionType assertion, long durationInMilis) throws ConfigurationException, - IssueInstantMissingException { + IssueInstantMissingException { XMLGregorianCalendar issueInstant = assertion.getIssueInstant(); if (issueInstant == null) throw new IssueInstantMissingException(ErrorCodes.NULL_ISSUE_INSTANT); @@ -211,7 +212,7 @@ public static void createTimedConditions(AssertionType assertion, long durationI * @throws IssueInstantMissingException */ public static void createTimedConditions(AssertionType assertion, long durationInMilis, long clockSkew) - throws ConfigurationException, IssueInstantMissingException { + throws ConfigurationException, IssueInstantMissingException { XMLGregorianCalendar issueInstant = assertion.getIssueInstant(); if (issueInstant == null) throw logger.samlIssueInstantMissingError(); @@ -237,7 +238,7 @@ public static void createTimedConditions(AssertionType assertion, long durationI * @throws IssueInstantMissingException */ public static void createSAML11TimedConditions(SAML11AssertionType assertion, long durationInMilis, long clockSkew) - throws ConfigurationException, IssueInstantMissingException { + throws ConfigurationException, IssueInstantMissingException { XMLGregorianCalendar issueInstant = assertion.getIssueInstant(); if (issueInstant == null) throw new IssueInstantMissingException(ErrorCodes.NULL_ISSUE_INSTANT); @@ -579,11 +580,11 @@ public static Element decryptAssertion(ResponseType responseType, PrivateKey pri */ public static Element decryptAssertion(ResponseType responseType, XMLEncryptionUtil.DecryptionKeyLocator decryptionKeyLocator) throws ParsingException, ProcessingException, ConfigurationException { Element enc = responseType.getAssertions().stream() - .map(ResponseType.RTChoiceType::getEncryptedAssertion) - .filter(Objects::nonNull) - .findFirst() - .map(EncryptedElementType::getEncryptedElement) - .orElseThrow(() -> new ProcessingException("No encrypted assertion found.")); + .map(ResponseType.RTChoiceType::getEncryptedAssertion) + .filter(Objects::nonNull) + .findFirst() + .map(EncryptedElementType::getEncryptedElement) + .orElseThrow(() -> new ProcessingException("No encrypted assertion found.")); String oldID = enc.getAttribute(JBossSAMLConstants.ID.get()); Document newDoc = DocumentUtil.createDocument(); @@ -595,7 +596,7 @@ public static Element decryptAssertion(ResponseType responseType, XMLEncryptionU JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement); AssertionType assertion = (AssertionType) parser.parse(parser.createEventReader(DocumentUtil - .getNodeAsStream(decryptedDocumentElement))); + .getNodeAsStream(decryptedDocumentElement))); responseType.replaceAssertion(oldID, new ResponseType.RTChoiceType(assertion)); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java index 4ef3e6b..d4b1603 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java @@ -12,7 +12,8 @@ import org.keycloak.dom.saml.v2.metadata.LocalizedNameType; import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType; import org.keycloak.saml.common.PicketLinkLogger; -import org.keycloak.saml.common.PicketLinkLoggerFactory; +import nl.first8.keycloak.saml.common.PicketLinkLoggerFactory; +import org.jboss.logging.Logger; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.util.StaxUtil; @@ -38,7 +39,7 @@ public class BaseWriter { - protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); + protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(Logger.getLogger(BaseWriter.class)); protected static String PROTOCOL_PREFIX = "samlp"; @@ -176,7 +177,7 @@ public void writeAttributeTypeWithoutRootTag(AttributeType attributeType) throws private void writeElementAttributeValue(Element attributeValue) throws ProcessingException { StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.ATTRIBUTE_VALUE.get(), - ASSERTION_NSURI.get()); + ASSERTION_NSURI.get()); StaxUtil.writeDOMElement(writer, attributeValue); StaxUtil.writeEndElement(writer); } @@ -221,7 +222,7 @@ public void writeDateAttributeValue(XMLGregorianCalendar attributeValue) throws public void writeLocalizedNameType(LocalizedNameType localizedNameType, QName startElement) throws ProcessingException { StaxUtil.writeStartElement(writer, startElement.getPrefix(), startElement.getLocalPart(), - startElement.getNamespaceURI()); + startElement.getNamespaceURI()); StaxUtil.writeAttribute(writer, new QName(JBossSAMLURIConstants.XML.get(), "lang", "xml"), localizedNameType.getLang()); StaxUtil.writeCharacters(writer, localizedNameType.getValue()); StaxUtil.writeEndElement(writer); @@ -290,7 +291,7 @@ public void write(ExtensionsType extensions) throws ProcessingException { private void write(SubjectConfirmationType subjectConfirmationType) throws ProcessingException { StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.SUBJECT_CONFIRMATION.get(), - ASSERTION_NSURI.get()); + ASSERTION_NSURI.get()); StaxUtil.writeAttribute(writer, JBossSAMLConstants.METHOD.get(), subjectConfirmationType.getMethod()); @@ -311,7 +312,7 @@ private void write(SubjectConfirmationType subjectConfirmationType) throws Proce private void write(SubjectConfirmationDataType subjectConfirmationData) throws ProcessingException { StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.SUBJECT_CONFIRMATION_DATA.get(), - ASSERTION_NSURI.get()); + ASSERTION_NSURI.get()); // Let us look at attributes String inResponseTo = subjectConfirmationData.getInResponseTo(); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/util/XMLSignatureUtil.java b/src/main/java/nl/first8/keycloak/saml/processing/core/util/XMLSignatureUtil.java index 7893bdb..c163e03 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/util/XMLSignatureUtil.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/util/XMLSignatureUtil.java @@ -2,6 +2,7 @@ import nl.first8.keycloak.saml.common.constants.GeneralConstants; import nl.first8.keycloak.saml.common.constants.JBossSAMLConstants; +import org.jboss.logging.Logger; import org.keycloak.common.util.Base64; import org.keycloak.common.util.PemUtils; import org.keycloak.dom.xmlsec.w3.xmldsig.DSAKeyValueType; @@ -9,9 +10,8 @@ import org.keycloak.dom.xmlsec.w3.xmldsig.RSAKeyValueType; import org.keycloak.dom.xmlsec.w3.xmldsig.SignatureType; import org.keycloak.saml.common.PicketLinkLogger; -import org.keycloak.saml.common.PicketLinkLoggerFactory; +import nl.first8.keycloak.saml.common.PicketLinkLoggerFactory; import org.keycloak.saml.common.constants.WSTrustConstants; -import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.util.*; @@ -54,7 +54,8 @@ public class XMLSignatureUtil { - private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); + private static final PicketLinkLogger logger = + PicketLinkLoggerFactory.getLogger(Logger.getLogger(XMLSignatureUtil.class)); // Set some system properties and Santuario providers. Run this block before any other class initialization. static { @@ -92,7 +93,8 @@ public KeySelectorResult select(KeyInfo keyInfo, KeySelector.Purpose purpose, Al final Key key = locator.getKey(keyInfo); this.keyLocated = key != null; return new KeySelectorResult() { - @Override public Key getKey() { + @Override + public Key getKey() { return key; } }; @@ -172,7 +174,6 @@ public KeySelectorResult select(KeyInfo ki, KeySelector.Purpose prps, AlgorithmM * Use this method to not include the KeyInfo in the signature * * @param includeKeyInfoInSignature - * * @since v2.0.1 */ public static void setIncludeKeyInfoInSignature(boolean includeKeyInfoInSignature) { @@ -188,9 +189,7 @@ public static void setIncludeKeyInfoInSignature(boolean includeKeyInfoInSignatur * @param digestMethod * @param signatureMethod * @param referenceURI - * * @return - * * @throws ParserConfigurationException * @throws XMLSignatureException * @throws MarshalException @@ -199,7 +198,7 @@ public static void setIncludeKeyInfoInSignature(boolean includeKeyInfoInSignatur public static Document sign(Document doc, Node nodeToBeSigned, String keyName, KeyPair keyPair, String digestMethod, String signatureMethod, String referenceURI, X509Certificate x509Certificate, String canonicalizationMethodType) throws ParserConfigurationException, GeneralSecurityException, - MarshalException, XMLSignatureException { + MarshalException, XMLSignatureException { if (nodeToBeSigned == null) { logger.error("Node to be signed is null"); throw logger.nullArgumentError("Node to be signed"); @@ -225,7 +224,7 @@ public static Document sign(Document doc, Node nodeToBeSigned, String keyName, K // if the signed element is a SAMLv2.0 assertion we need to move the signature element to the position // specified in the schema (before the assertion subject element). if (nodeToBeSigned.getLocalName().equals("Assertion") - && WSTrustConstants.SAML2_ASSERTION_NS.equals(nodeToBeSigned.getNamespaceURI())) { + && WSTrustConstants.SAML2_ASSERTION_NS.equals(nodeToBeSigned.getNamespaceURI())) { Node signatureNode = DocumentUtil.getElement(newDoc, new QName(WSTrustConstants.DSIG_NS, "Signature")); Node subjectNode = DocumentUtil.getElement(newDoc, new QName(WSTrustConstants.SAML2_ASSERTION_NS, "Subject")); if (signatureNode != null && subjectNode != null) { @@ -250,34 +249,32 @@ public static Document sign(Document doc, Node nodeToBeSigned, String keyName, K /** * Sign only specified element (assumption is that it already has ID attribute set) * - * @param elementToSign element to sign with set ID - * @param nextSibling child of elementToSign, which will be used as next sibling of created signature + * @param elementToSign element to sign with set ID + * @param nextSibling child of elementToSign, which will be used as next sibling of created signature * @param keyPair * @param digestMethod * @param signatureMethod * @param referenceURI - * * @throws GeneralSecurityException * @throws MarshalException * @throws XMLSignatureException */ public static void sign(Element elementToSign, Node nextSibling, String keyName, KeyPair keyPair, String digestMethod, String signatureMethod, String referenceURI, String canonicalizationMethodType) - throws GeneralSecurityException, MarshalException, XMLSignatureException { + throws GeneralSecurityException, MarshalException, XMLSignatureException { sign(elementToSign, nextSibling, keyName, keyPair, digestMethod, signatureMethod, referenceURI, null, canonicalizationMethodType); } /** * Sign only specified element (assumption is that it already has ID attribute set) * - * @param elementToSign element to sign with set ID - * @param nextSibling child of elementToSign, which will be used as next sibling of created signature + * @param elementToSign element to sign with set ID + * @param nextSibling child of elementToSign, which will be used as next sibling of created signature * @param keyPair * @param digestMethod * @param signatureMethod * @param referenceURI * @param x509Certificate {@link X509Certificate} to be placed in SignedInfo - * * @throws GeneralSecurityException * @throws MarshalException * @throws XMLSignatureException @@ -285,7 +282,7 @@ public static void sign(Element elementToSign, Node nextSibling, String keyName, */ public static void sign(Element elementToSign, Node nextSibling, String keyName, KeyPair keyPair, String digestMethod, String signatureMethod, String referenceURI, X509Certificate x509Certificate, String canonicalizationMethodType) - throws GeneralSecurityException, MarshalException, XMLSignatureException { + throws GeneralSecurityException, MarshalException, XMLSignatureException { PrivateKey signingKey = keyPair.getPrivate(); PublicKey publicKey = keyPair.getPublic(); @@ -311,19 +308,28 @@ public static void propagateIDAttributeSetup(Node sourceNode, Element destElemen } } - public static void fixIDAttributeSetup(Node sourceNode, Element destElement) { - if(sourceNode == null) { - logger.debug("Cannot fix AttributeSetup as sourcenode is NULL"); + public static void fixIDAttributeSetup(Element element) { + if (element == null) { + logger.info("Cannot fix AttributeSetup as element is NULL"); return; } - NamedNodeMap nnm = sourceNode.getAttributes(); + NamedNodeMap nnm = element.getAttributes(); for (int i = 0; i < nnm.getLength(); i++) { Attr attr = (Attr) nnm.item(i); if (attr.getName().equals("ID")) { - destElement.setIdAttribute(attr.getName(), true); + element.setIdAttribute(attr.getName(), true); break; } } + + // recursively fix + NodeList childNodes = element.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node item = childNodes.item(i); + if (item instanceof Element) { + fixIDAttributeSetup((Element) item); + } + } } /** @@ -333,15 +339,13 @@ public static void fixIDAttributeSetup(Node sourceNode, Element destElement) { * @param digestMethod * @param signatureMethod * @param referenceURI - * * @return - * * @throws GeneralSecurityException * @throws XMLSignatureException * @throws MarshalException */ public static Document sign(Document doc, String keyName, KeyPair keyPair, String digestMethod, String signatureMethod, String referenceURI, String canonicalizationMethodType) - throws GeneralSecurityException, MarshalException, XMLSignatureException { + throws GeneralSecurityException, MarshalException, XMLSignatureException { return sign(doc, keyName, keyPair, digestMethod, signatureMethod, referenceURI, null, canonicalizationMethodType); } @@ -352,9 +356,7 @@ public static Document sign(Document doc, String keyName, KeyPair keyPair, Strin * @param digestMethod * @param signatureMethod * @param referenceURI - * * @return - * * @throws GeneralSecurityException * @throws XMLSignatureException * @throws MarshalException @@ -362,7 +364,7 @@ public static Document sign(Document doc, String keyName, KeyPair keyPair, Strin */ public static Document sign(Document doc, String keyName, KeyPair keyPair, String digestMethod, String signatureMethod, String referenceURI, X509Certificate x509Certificate, String canonicalizationMethodType) - throws GeneralSecurityException, MarshalException, XMLSignatureException { + throws GeneralSecurityException, MarshalException, XMLSignatureException { if (logger.isTraceEnabled()) { logger.trace("Document to be signed=" + DocumentUtil.asString(doc)); } @@ -379,15 +381,13 @@ public static Document sign(Document doc, String keyName, KeyPair keyPair, Strin /** * Sign the root element * - * * @return - * * @throws GeneralSecurityException * @throws XMLSignatureException * @throws MarshalException */ public static Document sign(SignatureUtilTransferObject dto, String canonicalizationMethodType) throws GeneralSecurityException, MarshalException, - XMLSignatureException { + XMLSignatureException { Document doc = dto.getDocumentToBeSigned(); String keyName = dto.getKeyName(); KeyPair keyPair = dto.getKeyPair(); @@ -414,34 +414,16 @@ public static Document sign(SignatureUtilTransferObject dto, String canonicaliza return doc; } - /** - * Validate a signed document with the given public key. All elements that contain a Signature are checked, - * this way both assertions and the containing document are verified when signed. - * - * @param signedDoc - * @param locator - * - * @return - * - * @throws MarshalException - * @throws XMLSignatureException - */ - @SuppressWarnings("unchecked") public static boolean validate(Document signedDoc, final KeyLocator locator) throws MarshalException, XMLSignatureException { - logger.warn("Called without configuration for Saml Advice Nodes: defaulting to false."); - return validate(signedDoc, locator, false); - } - - public static boolean validate(Document signedDoc, final KeyLocator locator, boolean ignoreAdviceNodes) throws MarshalException, XMLSignatureException { - logger.debug("Validate document " + signedDoc.getDocumentURI()); if (signedDoc == null) throw logger.nullArgumentError("Signed Document"); + fixIDAttributeSetup(signedDoc.getDocumentElement()); propagateIDAttributeSetup(signedDoc.getDocumentElement(), signedDoc.getDocumentElement()); NodeList nl = signedDoc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); if (nl == null || nl.getLength() == 0) { - logger.debug("Cannot find Signature element"); + logger.warn("Cannot find Signature element, returning false"); return false; } @@ -450,45 +432,51 @@ public static boolean validate(Document signedDoc, final KeyLocator locator, boo HashSet signedNodes = new HashSet<>(); + // Change from keycloak: always check all signatures and report all failed signatures to make debugging easier. + boolean signatureValid = true; for (int i = 0; i < nl.getLength(); i++) { Node signatureNode = nl.item(i); - if (!validateSingleNode(signatureNode, locator, signedNodes)) { - return false; + logger.debug("Validating signature node #%d: %s".formatted((i + 1), signatureNode.getLocalName())); + + boolean nodeSignatureValid = validateSingleNode(signatureNode, locator, signedNodes); + if (nodeSignatureValid) { + logger.debug("Successfully validated SignatureNode #%d".formatted(i + 1)); + } else { + logger.warn("signatureNode #%d INVALID".formatted(i + 1)); } + signatureValid &= nodeSignatureValid; + } + if (!signatureValid) { + logger.warn("XMLSignatureUtil.validate returning false because one of the signatures was invalid"); + return false; } if (signedNodes.contains(signedDoc.getDocumentElement())) { - logger.trace("All signatures are OK and root document is signed"); + logger.trace("All signatures are OK and root document is signed, returning true"); return true; } NodeList assertions = signedDoc.getElementsByTagNameNS(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get()); if (assertions.getLength() > 0) { - // if document is not fully signed check if all the assertions are signed + logger.trace("The document is not fully signed, checking that all assertions are signed"); for (int i = 0; i < assertions.getLength(); i++) { if (!signedNodes.contains(assertions.item(i))) { - logger.debug("SAML Response document may contain malicious assertions. Signature validation will fail."); - // there are unsigned assertions mixed with signed ones + logger.warn("There are unsigned assertions mixed with signed ones, document may contain malicious assertions, returning false for signature validation"); return false; } } - logger.trace("Document not signed but all assertions are signed OK"); + logger.trace("Document is not signed but all assertions are signed OK, returning true"); return true; } + logger.warn("fall-through reached, this is unexpected, signature validation returning false"); return false; } - private static Node getSamlReponseNode(Document signedDoc) { - Node samlReponseNode = signedDoc.getElementsByTagName("saml2p:Response").item(0); - if(samlReponseNode == null) { - samlReponseNode = signedDoc.getElementsByTagName("samlp:Response").item(0); - } - return samlReponseNode; - } - - public static boolean validateSingleNode(Node signatureNode, final KeyLocator locator) throws MarshalException, XMLSignatureException { + public static boolean validateSingleNode(Node signatureNode, final KeyLocator locator) throws + MarshalException, XMLSignatureException { + logger.debug("validateSingleNode called without Set signedNodes, using new HashSet<>() for that."); return validateSingleNode(signatureNode, locator, new HashSet<>()); } @@ -499,6 +487,7 @@ public static boolean validateSingleNode(Node signatureNode, final KeyLocator lo return true; } if (sel.wasKeyLocated()) { + logger.warn("the key was located, could not validate node, validateSingleNode returns false"); return false; } } catch (XMLSignatureException ex) { // pass through MarshalException @@ -506,8 +495,7 @@ public static boolean validateSingleNode(Node signatureNode, final KeyLocator lo logger.trace(ex); } - logger.trace("Could not validate signature using ds:KeyInfo/ds:KeyName hint."); - + logger.debug("Could not validate signature using ds:KeyInfo/ds:KeyName hint."); logger.trace("Trying hard to validate XML signature using all available keys."); for (Key key : locator) { @@ -521,19 +509,15 @@ public static boolean validateSingleNode(Node signatureNode, final KeyLocator lo } } + logger.warn("validateSingleNode fall through reached, no key could validate the signature, returning false "); return false; } + private static boolean validateUsingKeySelector(Node signatureNode, KeySelector validationKeySelector, Set signedNodes) throws XMLSignatureException, MarshalException { DOMValidateContext valContext = new DOMValidateContext(validationKeySelector, signatureNode); XMLSignature signature = fac.unmarshalXMLSignature(valContext); - if(logger.isDebugEnabled()) { - try { - logger.debug("ValContext: " + DocumentUtil.getNodeAsString(signatureNode) + " signature: " + signature.getSignatureValue().getId()); - } catch (ProcessingException | ConfigurationException e) { - logger.warn("Could not print DEBUG information about ValContext. Will continue"); - } - } + boolean coreValidity = signature.validate(valContext); if (coreValidity) { @@ -565,23 +549,11 @@ private static boolean validateUsingKeySelector(Node signatureNode, KeySelector return coreValidity; } - private static void setIdAttributeNS(String tagName, Node signatureNode, DOMValidateContext valContext) { - NodeList elements = signatureNode.getOwnerDocument().getElementsByTagName(tagName); - for (int index = 0; index < elements.getLength(); index++) { - Element element = (Element) elements.item(index); - if(logger.isDebugEnabled()) { - logger.debug("Setting ID ("+element.getAttributeNode("ID").getValue()+") attribute on "+element.getTagName()+" as ID Attribute"); - } - valContext.setIdAttributeNS(element, null, "ID"); - } - } - /** * Marshall a SignatureType to output stream * * @param signature * @param os - * * @throws SAXException * @throws JAXBException */ @@ -598,7 +570,6 @@ public static void marshall(SignatureType signature, OutputStream os) throws JAX * * @param signedDocument * @param os - * * @throws TransformerException */ public static void marshall(Document signedDocument, OutputStream os) throws TransformerException { @@ -611,10 +582,8 @@ public static void marshall(Document signedDocument, OutputStream os) throws Tra * Given the X509Certificate in the keyinfo element, get a {@link X509Certificate} * * @param certificateString - * * @return - * - * @throws org.keycloak.saml.common.exceptions.ProcessingException + * @throws ProcessingException */ public static X509Certificate getX509CertificateFromKeyInfoString(String certificateString) throws ProcessingException { X509Certificate cert = null; @@ -640,9 +609,7 @@ public static X509Certificate getX509CertificateFromKeyInfoString(String certifi * Given a dsig:DSAKeyValue element, return {@link DSAKeyValueType} * * @param element - * * @return - * * @throws ProcessingException */ public static DSAKeyValueType getDSAKeyValue(Element element) throws ParsingException { @@ -681,9 +648,7 @@ public static DSAKeyValueType getDSAKeyValue(Element element) throws ParsingExce * Given a dsig:DSAKeyValue element, return {@link DSAKeyValueType} * * @param element - * * @return - * * @throws ProcessingException */ public static RSAKeyValueType getRSAKeyValue(Element element) throws ParsingException { @@ -716,9 +681,8 @@ public static RSAKeyValueType getRSAKeyValue(Element element) throws ParsingExce *

* * @param key the {@code PublicKey} that will be represented as a {@code KeyValueType}. - * * @return the constructed {@code KeyValueType} or {@code null} if the specified key is neither a DSA nor a RSA - * key. + * key. */ public static KeyValueType createKeyValue(PublicKey key) { if (key instanceof RSAPublicKey) { @@ -749,7 +713,7 @@ public static KeyValueType createKeyValue(PublicKey key) { private static void signImpl(DOMSignContext dsc, String digestMethod, String signatureMethod, String referenceURI, String keyName, PublicKey publicKey, X509Certificate x509Certificate, String canonicalizationMethodType) - throws GeneralSecurityException, MarshalException, XMLSignatureException { + throws GeneralSecurityException, MarshalException, XMLSignatureException { dsc.setDefaultNamespacePrefix("dsig"); DigestMethod digestMethodObj = fac.newDigestMethod(digestMethod, null); @@ -763,7 +727,7 @@ private static void signImpl(DOMSignContext dsc, String digestMethod, String sig Reference ref = fac.newReference(referenceURI, digestMethodObj, transformList, null, null); CanonicalizationMethod canonicalizationMethod = fac.newCanonicalizationMethod(canonicalizationMethodType, - (C14NMethodParameterSpec) null); + (C14NMethodParameterSpec) null); List referenceList = Collections.singletonList(ref); SignatureMethod signatureMethodObj = fac.newSignatureMethod(signatureMethod, null); diff --git a/src/main/resources/saml-extended-frontend/js/AddProvider.js b/src/main/resources/saml-extended-frontend/js/AddProvider.js index e27ccbf..5ae7c9b 100644 --- a/src/main/resources/saml-extended-frontend/js/AddProvider.js +++ b/src/main/resources/saml-extended-frontend/js/AddProvider.js @@ -3,7 +3,7 @@ import_data.addEventListener('click', async (event) => { event.preventDefault(); let alias = alias_input.value; keycloak.updateToken(300).then(async (bool) => { - + if (bool) { let isValid = true; hasFocused = false; @@ -21,20 +21,20 @@ import_data.addEventListener('click', async (event) => { { handleValidInput(samlEntityDescriptor_input, samlEntityDescriptor_errorMessage_URL,""); } handleValidInput(Single_Sign_On_Service_URL_input, errorMessage_URL,""); - - - + + + if (!isValid) {return} var newAccessToken = keycloak.token; - - const checkPluginResponse = await fetch(`${ServerUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${alias}`, { + + const checkPluginResponse = await fetch(`${serverUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${alias}`, { method: 'GET', headers: { 'Authorization': `Bearer ${newAccessToken}` } }); - + if (checkPluginResponse.ok) { alias_input.classList.remove('input_text'); alias_input.classList.add('red-border'); @@ -44,7 +44,7 @@ import_data.addEventListener('click', async (event) => { // Add your logic for updating the existing plugin if needed } else if (checkPluginResponse.status === 404) { // Plugin not found, add it using a POST request - const updatePluginResponse = await fetch(`${ServerUrl}/admin/realms/${selectedrealm}/identity-provider/import-config`, { + const updatePluginResponse = await fetch(`${serverUrl}/admin/realms/${selectedrealm}/identity-provider/import-config`, { method: 'POST', headers: { 'Authorization': `Bearer ${newAccessToken}`, @@ -55,7 +55,7 @@ import_data.addEventListener('click', async (event) => { fromUrl: `${samlEntityDescriptor.value}` }) }); - + if (updatePluginResponse.ok) { const config = await updatePluginResponse.json(); samlEntityDescriptor_input.classList.remove('red-border'); @@ -64,13 +64,13 @@ import_data.addEventListener('click', async (event) => { importClicked = true; document.getElementById("submit").disabled = false var data = - {"alias": alias, "enabled": "true", - "providerId": "saml-extended", "config": { - "allowCreate": "true", - ...config - } - - }; + {"alias": alias, "enabled": "true", + "providerId": "saml-extended", "config": { + "allowCreate": "true", + ...config + } + + }; var script = document.createElement('script'); localStorage.setItem('pluginData', JSON.stringify(data)); script.src = '../../samlconfig/js/InfoUpdaterAdd'; @@ -102,21 +102,21 @@ add.addEventListener('click', () => { else { handleValidInput(samlEntityDescriptor_input, samlEntityDescriptor_errorMessage_URL,""); } - - if (!Single_Sign_On_Service_URL_input.value || !Single_Sign_On_Service_URL_input.value.startsWith("https://")) { - handleInvalidInput(Single_Sign_On_Service_URL_input, errorMessage_URL, "Enter a valid URL"); - isValid = false; - } else { - handleValidInput(Single_Sign_On_Service_URL_input, errorMessage_URL,""); - } - - if (Single_Logout_Service_URL_input.value && !Single_Logout_Service_URL_input.value.startsWith("https://")) { - handleInvalidInput(Single_Logout_Service_URL_input, errorMessage_URL_logout, "Enter a valid URL"); - isValid = false; - } else { - handleValidInput(Single_Logout_Service_URL_input, errorMessage_URL_logout,""); - } - + + if (!Single_Sign_On_Service_URL_input.value || !Single_Sign_On_Service_URL_input.value.startsWith("https://")) { + handleInvalidInput(Single_Sign_On_Service_URL_input, errorMessage_URL, "Enter a valid URL"); + isValid = false; + } else { + handleValidInput(Single_Sign_On_Service_URL_input, errorMessage_URL,""); + } + + if (Single_Logout_Service_URL_input.value && !Single_Logout_Service_URL_input.value.startsWith("https://")) { + handleInvalidInput(Single_Logout_Service_URL_input, errorMessage_URL_logout, "Enter a valid URL"); + isValid = false; + } else { + handleValidInput(Single_Logout_Service_URL_input, errorMessage_URL_logout,""); + } + if (!isValid) { return; } @@ -124,15 +124,15 @@ add.addEventListener('click', () => { handleInvalidInput(samlEntityDescriptor_input, samlEntityDescriptor_errorMessage_URL, "Make sure to press the import button first"); return; } - + const data = JSON.parse(localStorage.getItem('pluginData')); - + keycloak.updateToken(300).then(async (bool) => { if (bool) { var newAccessToken = keycloak.token; var selectedrealm = localStorage.getItem('selectedRealm'); - - const updatePluginResponse = await fetch(`${ServerUrl}/admin/realms/${selectedrealm}/identity-provider/instances`, { + + const updatePluginResponse = await fetch(`${serverUrl}/admin/realms/${selectedrealm}/identity-provider/instances`, { method: 'POST', headers: { 'Authorization': `Bearer ${newAccessToken}`, @@ -140,7 +140,7 @@ add.addEventListener('click', () => { }, body: JSON.stringify(data), }); - + if (updatePluginResponse.ok) { alert("Plugin added successfully."); window.location.href = `${editprovider}`; @@ -172,12 +172,12 @@ add.addEventListener('click', () => { var element = document.querySelector(selector); return element ? element.value.trim() : null; } - + var serviceName = getValueFromElement('.serviceName'); var attributeValue = getValueFromElement('.attributeValue'); var friendlyName = getValueFromElement('.friendlyName'); var attributeName = getValueFromElement('.attributeName'); - + var Single_Sign_On_Service_URL = Single_Sign_On_Service_URL_input.value; var Single_Logout_Service_URL = Single_Logout_Service_URL_input.value; var nameIdPolicy = nameIdPolicy_input.value; @@ -200,6 +200,7 @@ add.addEventListener('click', () => { "postBindingLogout": httpPostBindingLogout.value, "authnContextClassRefs": authnContextClassRefs.length > 0 ? JSON.stringify(authnContextClassRefs) : undefined, "postBindingResponse": httpPostBindingResponse.value, + "artifactBindingResponse": artifactBindingResponse.value, "singleLogoutServiceUrl": Single_Logout_Service_URL, "authnContextDeclRefs": authnContextDeclRefs.length > 0 ? JSON.stringify(authnContextDeclRefs) : undefined, "backchannelSupported": backchannel.value, @@ -226,6 +227,7 @@ add.addEventListener('click', () => { "wantAssertionsSigned": wantAssertionsSigned.value, "postBindingAuthnRequest":httpPostBindingAuthnRequest.value, "forceAuthn": forceAuthentication.value, + "assertionConsumingServiceIndex": assertionConsumingServiceIndex_input.value, "attributeConsumingServiceIndex": attributeConsumingServiceIndex_input.value, "principalType": principalType_input.value, "principalAttribute": principalAttribute_input.value, @@ -235,7 +237,6 @@ add.addEventListener('click', () => { "signArtifactResolutionRequest": Sign_Artifact_Resolution_Request.value, "artifactResolutionSOAP": Artifact_Resolution_with_SOAP.value, "artifactResolutionWithXmlHeader": Artifact_Resolution_with_XML_header.value, - "artifactResolutionHTTPArtifact": ArtifactResolution_via_HTTP_ARTIFACT.value, "mutualTls": Mutual_TLS.value, "charSet": CharacterSet_input.value, "metadataValidUntilUnit": Metadata_expires_in_input.value, @@ -246,106 +247,106 @@ add.addEventListener('click', () => { "enabledFromMetadata": useEntityDescriptor.value, "metadataDescriptorUrl": samlEntityDescriptor_input.value, "attributeConsumingServiceMetadata":attributeServicesArray.length > 0 ? JSON.stringify(attributeServicesArray) : undefined - + }} - - let isValid = true; - hasFocused = false; - if (!alias_input.value) { - handleInvalidInput(alias_input, errorMessage, "Required field !"); - isValid = false; - } else { - handleValidInput(alias_input, errorMessage,""); - } - - if (!Single_Sign_On_Service_URL_input.value || !Single_Sign_On_Service_URL_input.value.startsWith("https://")) { - handleInvalidInput(Single_Sign_On_Service_URL_input, errorMessage_URL, "Enter a valid URL"); - isValid = false; - } else { - handleValidInput(Single_Sign_On_Service_URL_input, errorMessage_URL,""); - } - - if (Single_Logout_Service_URL_input.value && !Single_Logout_Service_URL_input.value.startsWith("https://")) { - handleInvalidInput(Single_Logout_Service_URL_input, errorMessage_URL_logout, "Enter a valid URL"); - isValid = false; - } else { - handleValidInput(Single_Logout_Service_URL_input, errorMessage_URL_logout,""); - } - - if (!isValid) { - return; + + let isValid = true; + hasFocused = false; + if (!alias_input.value) { + handleInvalidInput(alias_input, errorMessage, "Required field !"); + isValid = false; + } else { + handleValidInput(alias_input, errorMessage,""); + } + + if (!Single_Sign_On_Service_URL_input.value || !Single_Sign_On_Service_URL_input.value.startsWith("https://")) { + handleInvalidInput(Single_Sign_On_Service_URL_input, errorMessage_URL, "Enter a valid URL"); + isValid = false; + } else { + handleValidInput(Single_Sign_On_Service_URL_input, errorMessage_URL,""); + } + + if (Single_Logout_Service_URL_input.value && !Single_Logout_Service_URL_input.value.startsWith("https://")) { + handleInvalidInput(Single_Logout_Service_URL_input, errorMessage_URL_logout, "Enter a valid URL"); + isValid = false; + } else { + handleValidInput(Single_Logout_Service_URL_input, errorMessage_URL_logout,""); + } + + if (!isValid) { + return; + } + + removeEmptyStrings(data); + + const configKeys = Object.keys(data.config); + for (const key of configKeys) { + if (typeof data.config[key] === 'string' && data.config[key].trim() === "") { + delete data.config[key]; } - - removeEmptyStrings(data); - - const configKeys = Object.keys(data.config); - for (const key of configKeys) { - if (typeof data.config[key] === 'string' && data.config[key].trim() === "") { - delete data.config[key]; } - } - if (Array.isArray(data.config.authnContextClassRefs) && data.config.authnContextClassRefs.length === 0) { - delete data.config.authnContextClassRefs; - } - - if (Array.isArray(data.config.authnContextDeclRefs) && data.config.authnContextDeclRefs.length === 0) { - delete data.config.authnContextDeclRefs; - } - - // Update token and execute the following code when the token is successfully updated - keycloak.updateToken(300).then((bool) => { - if (bool) { - - // Code to be executed after token update - var newAccessToken = keycloak.token; - var selectedrealm= localStorage.getItem('selectedRealm'); - // Sending a GET request to check if the plugin exists - fetch(`${ServerUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${alias}`, { - method: 'GET', - headers: { - 'Authorization': ` Bearer ${newAccessToken}`, // Fix here - }, - }) - .then(async checkPluginResponse => { - if (checkPluginResponse.ok) { - handleInvalidInput(alias_input, errorMessage, "Choose a unique *alias* that does not exist"); - alert(`Could not create the identity provider: Identity Provider "${alias}" already exists.`); - // Add your logic for updating the existing plugin if needed - } else if (checkPluginResponse.status === 404) { - // Plugin not found, add it using a POST request - const updatePluginResponse = await fetch(`${ServerUrl}/admin/realms/${selectedrealm}/identity-provider/instances`, { - method: 'POST', - headers: { - 'Authorization': ` Bearer ${newAccessToken}`, // Fix here - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - } - - ); - - // Handle the response of the POST request - if (updatePluginResponse.ok) { - alert("Plugin added successfully."); - window.location.href =`${editprovider}`; - localStorage.setItem('pluginData', JSON.stringify(data)); - localStorage.setItem('pluginalias', pluginData.alias); - getAllPlugins(newAccessToken,selectedrealm); - } else { - console.error('Failed to add plugin:', updatePluginResponse.status, updatePluginResponse.statusText); - alert("Failed to add plugin"); - } - } else { - // If there is another status, an error occurred - console.error(`Failed to retrieve the plugin. Response: ${checkPluginResponse.statusText}`); - alert("Failed to retrieve the plugin"); - throw new Error(`Failed to retrieve the plugin. Response: ${checkPluginResponse.statusText}`); - } - }) - .catch(error => { - console.error('Error during the process:', error); - }); + if (Array.isArray(data.config.authnContextClassRefs) && data.config.authnContextClassRefs.length === 0) { + delete data.config.authnContextClassRefs; } - - }); -}}); + + if (Array.isArray(data.config.authnContextDeclRefs) && data.config.authnContextDeclRefs.length === 0) { + delete data.config.authnContextDeclRefs; + } + + // Update token and execute the following code when the token is successfully updated + keycloak.updateToken(300).then((bool) => { + if (bool) { + + // Code to be executed after token update + var newAccessToken = keycloak.token; + var selectedrealm= localStorage.getItem('selectedRealm'); + // Sending a GET request to check if the plugin exists + fetch(`${serverUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${alias}`, { + method: 'GET', + headers: { + 'Authorization': ` Bearer ${newAccessToken}`, // Fix here + }, + }) + .then(async checkPluginResponse => { + if (checkPluginResponse.ok) { + handleInvalidInput(alias_input, errorMessage, "Choose a unique *alias* that does not exist"); + alert(`Could not create the identity provider: Identity Provider "${alias}" already exists.`); + // Add your logic for updating the existing plugin if needed + } else if (checkPluginResponse.status === 404) { + // Plugin not found, add it using a POST request + const updatePluginResponse = await fetch(`${serverUrl}/admin/realms/${selectedrealm}/identity-provider/instances`, { + method: 'POST', + headers: { + 'Authorization': ` Bearer ${newAccessToken}`, // Fix here + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + } + + ); + + // Handle the response of the POST request + if (updatePluginResponse.ok) { + alert("Plugin added successfully."); + window.location.href =`${editprovider}`; + localStorage.setItem('pluginData', JSON.stringify(data)); + localStorage.setItem('pluginalias', pluginData.alias); + getAllPlugins(newAccessToken,selectedrealm); + } else { + console.error('Failed to add plugin:', updatePluginResponse.status, updatePluginResponse.statusText); + alert("Failed to add plugin"); + } + } else { + // If there is another status, an error occurred + console.error(`Failed to retrieve the plugin. Response: ${checkPluginResponse.statusText}`); + alert("Failed to retrieve the plugin"); + throw new Error(`Failed to retrieve the plugin. Response: ${checkPluginResponse.statusText}`); + } + }) + .catch(error => { + console.error('Error during the process:', error); + }); + } + + }); + }}); diff --git a/src/main/resources/saml-extended-frontend/js/CheckBoxControllerAddProvider.js b/src/main/resources/saml-extended-frontend/js/CheckBoxControllerAddProvider.js index 640e2a7..f810702 100644 --- a/src/main/resources/saml-extended-frontend/js/CheckBoxControllerAddProvider.js +++ b/src/main/resources/saml-extended-frontend/js/CheckBoxControllerAddProvider.js @@ -2,228 +2,228 @@ document.addEventListener('DOMContentLoaded', function() { const formElements = document.getElementById('GeneralSetting').elements; samlEntityDescriptor.addEventListener('input', function() { - if (samlEntityDescriptor.value.trim() !== '') { - import_data.style.display = 'block'; - } else { - import_data.style.display = 'none'; - } -}); - -document.getElementById('showMetadataLink').addEventListener('click', function(event) { - event.preventDefault(); - var data = document.getElementById('data'); - if (data.style.display === 'none'|| data.style.display === '') { - data.style.display = 'block'; - this.textContent = 'Hide Metadata'; - } else { - data.style.display = 'none'; - this.textContent = 'Show Metadata'; - } -}); -const useEntityDescriptor = document.getElementById("useEntityDescriptor"); -const entityDes=document.getElementById("entityDes") -const showMetadataLink=document.getElementById("showMetadataLink") -useEntityDescriptor.addEventListener("change", function () { - var data = document.getElementById('data'); - if (useEntityDescriptor.checked) { - useEntityDescriptor.value = "true"; - data.style.display = 'none'; - entityDes.style.display='block' - showMetadataLink.style.display='block' - for (var i = 0; i < formElements.length; i++) { - formElements[i].readOnly = true; - formElements[i].disabled = true; // for select elements + if (samlEntityDescriptor.value.trim() !== '') { + import_data.style.display = 'block'; + } else { + import_data.style.display = 'none'; } - - } else { - for (var i = 0; i < formElements.length; i++) { - formElements[i].readOnly = false; - formElements[i].disabled = false; // for select elements + }); + + document.getElementById('showMetadataLink').addEventListener('click', function(event) { + event.preventDefault(); + var data = document.getElementById('data'); + if (data.style.display === 'none'|| data.style.display === '') { + data.style.display = 'block'; + this.textContent = 'Hide Metadata'; + } else { + data.style.display = 'none'; + this.textContent = 'Show Metadata'; } - useEntityDescriptor.value = "false"; - data.style.display = 'block'; - entityDes.style.display='none' - showMetadataLink.style.display='none' - } -}); - -const backchannel = document.getElementById("backchannel"); -storedData = localStorage.getItem('pluginData'); -var pluginData = JSON.parse(storedData); - - -const enabled = document.getElementById("enabled"); -enabled.addEventListener("change", function () { - handleCheckboxValue(enabled); - -}); - -const ArtifactResolutionService_in_metadata = document.getElementById("ArtifactResolutionService_in_metadata"); -ArtifactResolutionService_in_metadata.addEventListener("change", function () { - handleCheckboxValue(ArtifactResolutionService_in_metadata); -}); - -backchannel.addEventListener("change", function () { - handleCheckboxValue(backchannel); -}); - - -const allowCreate = document.getElementById("allowCreate"); -allowCreate.addEventListener("change", function () { - handleCheckboxValue(allowCreate); - -}); - - - - -const httpPostBindingResponse = document.getElementById("httpPostBindingResponse"); -httpPostBindingResponse.addEventListener("change", function () { - handleCheckboxValue(httpPostBindingResponse); -}); - - - - - - -const httpPostBindingAuthnRequest = document.getElementById("httpPostBindingAuthnRequest"); -httpPostBindingAuthnRequest.addEventListener("change", function () { - handleCheckboxValue(httpPostBindingAuthnRequest); - -}); - -const httpPostBindingLogout = document.getElementById("httpPostBindingLogout"); -httpPostBindingLogout.addEventListener("change", function () { - handleCheckboxValue(httpPostBindingLogout); - -}); - - -const wantAssertionsSigned = document.getElementById("wantAssertionsSigned"); -wantAssertionsSigned.addEventListener("change", function () { - handleCheckboxValue(wantAssertionsSigned); - -}); - - -const wantAssertionsEncrypted = document.getElementById("wantAssertionsEncrypted"); -wantAssertionsEncrypted.addEventListener("change", function () { - handleCheckboxValue(wantAssertionsEncrypted); - -}); - - -const forceAuthentication = document.getElementById("forceAuthentication"); -forceAuthentication.addEventListener("change", function () { - handleCheckboxValue(forceAuthentication); - -}); - - - -const signMetadata = document.getElementById("signMetadata"); -signMetadata.addEventListener("change", function () { - handleCheckboxValue(signMetadata); - -}); - - -const passSubject = document.getElementById("passSubject"); -passSubject.addEventListener("change", function () { - handleCheckboxValue(passSubject); - -}); - - -const storeToken = document.getElementById("storeToken"); -storeToken.addEventListener("change", function () { - handleCheckboxValue(storeToken); - -}); -const id_token_hint=document.getElementById("id_token_hint"); + }); + const useEntityDescriptor = document.getElementById("useEntityDescriptor"); + const entityDes=document.getElementById("entityDes") + const showMetadataLink=document.getElementById("showMetadataLink") + useEntityDescriptor.addEventListener("change", function () { + var data = document.getElementById('data'); + if (useEntityDescriptor.checked) { + useEntityDescriptor.value = "true"; + data.style.display = 'none'; + entityDes.style.display='block' + showMetadataLink.style.display='block' + for (var i = 0; i < formElements.length; i++) { + formElements[i].readOnly = true; + formElements[i].disabled = true; // for select elements + } + + } else { + for (var i = 0; i < formElements.length; i++) { + formElements[i].readOnly = false; + formElements[i].disabled = false; // for select elements + } + useEntityDescriptor.value = "false"; + data.style.display = 'block'; + entityDes.style.display='none' + showMetadataLink.style.display='none' + } + }); + + const backchannel = document.getElementById("backchannel"); + storedData = localStorage.getItem('pluginData'); + var pluginData = JSON.parse(storedData); + + + const enabled = document.getElementById("enabled"); + enabled.addEventListener("change", function () { + handleCheckboxValue(enabled); + + }); + + const ArtifactResolutionService_in_metadata = document.getElementById("ArtifactResolutionService_in_metadata"); + ArtifactResolutionService_in_metadata.addEventListener("change", function () { + handleCheckboxValue(ArtifactResolutionService_in_metadata); + }); + + backchannel.addEventListener("change", function () { + handleCheckboxValue(backchannel); + }); + + + const allowCreate = document.getElementById("allowCreate"); + allowCreate.addEventListener("change", function () { + handleCheckboxValue(allowCreate); + + }); + + + + + const httpPostBindingResponse = document.getElementById("httpPostBindingResponse"); + httpPostBindingResponse.addEventListener("change", function () { + handleCheckboxValue(httpPostBindingResponse); + }); + + const artifactBindingResponse = document.getElementById("artifactBindingResponse"); + artifactBindingResponse.addEventListener("change", function () { + handleCheckboxValue(artifactBindingResponse); + }); + + const httpPostBindingAuthnRequest = document.getElementById("httpPostBindingAuthnRequest"); + httpPostBindingAuthnRequest.addEventListener("change", function () { + handleCheckboxValue(httpPostBindingAuthnRequest); + + }); + + const httpPostBindingLogout = document.getElementById("httpPostBindingLogout"); + httpPostBindingLogout.addEventListener("change", function () { + handleCheckboxValue(httpPostBindingLogout); + + }); + + + const wantAssertionsSigned = document.getElementById("wantAssertionsSigned"); + wantAssertionsSigned.addEventListener("change", function () { + handleCheckboxValue(wantAssertionsSigned); + + }); + + + const wantAssertionsEncrypted = document.getElementById("wantAssertionsEncrypted"); + wantAssertionsEncrypted.addEventListener("change", function () { + handleCheckboxValue(wantAssertionsEncrypted); + + }); + + + const forceAuthentication = document.getElementById("forceAuthentication"); + forceAuthentication.addEventListener("change", function () { + handleCheckboxValue(forceAuthentication); + + }); + + + + const signMetadata = document.getElementById("signMetadata"); + signMetadata.addEventListener("change", function () { + handleCheckboxValue(signMetadata); + + }); + + + const passSubject = document.getElementById("passSubject"); + passSubject.addEventListener("change", function () { + handleCheckboxValue(passSubject); + + }); + + + const storeToken = document.getElementById("storeToken"); + storeToken.addEventListener("change", function () { + handleCheckboxValue(storeToken); + + }); + const id_token_hint=document.getElementById("id_token_hint"); id_token_hint.addEventListener("change", function () { handleCheckboxValue(id_token_hint); - + }); - const client_id_in_logout_requests=document.getElementById("client_id_in_logout_requests") + const client_id_in_logout_requests=document.getElementById("client_id_in_logout_requests") client_id_in_logout_requests.addEventListener("change", function () { handleCheckboxValue(client_id_in_logout_requests); - + }); - -const storedTokensReadable = document.getElementById("storedTokensReadable"); -storedTokensReadable.addEventListener("change", function () { - handleCheckboxValue(storedTokensReadable); - -}); - - -const trustEmail = document.getElementById("trustEmail"); -trustEmail.addEventListener("change", function () { - handleCheckboxValue(trustEmail); - -}); - - - - -const accountLinkingOnly = document.getElementById("accountLinkingOnly"); -accountLinkingOnly.addEventListener("change", function () { - handleCheckboxValue(accountLinkingOnly); - -}); - - -const hideLoginPage = document.getElementById("hideLoginPage"); -hideLoginPage.addEventListener("change", function () { - handleCheckboxValue(hideLoginPage); - -}); - - -var SignatureAlgorithm = document.getElementById("SignatureAlgorithm"); -var SAMLSignatureKeyName = document.getElementById("SAMLSignatureKeyName"); - -const wantAuthnRequestsSigned = document.getElementById("wantAuthnRequestsSigned"); -wantAuthnRequestsSigned.addEventListener("change", function () { - if (wantAuthnRequestsSigned.checked) { - wantAuthnRequestsSigned.value = true; - SignatureAlgorithm.removeAttribute("disabled"); - SAMLSignatureKeyName.removeAttribute("disabled"); - encryption_algorithm.removeAttribute("disabled"); - - } - else { - wantAuthnRequestsSigned.value = false; - SignatureAlgorithm.setAttribute("disabled", "true"); - SAMLSignatureKeyName.setAttribute("disabled", "true"); - encryption_algorithm.setAttribute("disabled", "true"); - - - ; - } -}); - - + + const storedTokensReadable = document.getElementById("storedTokensReadable"); + storedTokensReadable.addEventListener("change", function () { + handleCheckboxValue(storedTokensReadable); + + }); + + + const trustEmail = document.getElementById("trustEmail"); + trustEmail.addEventListener("change", function () { + handleCheckboxValue(trustEmail); + + }); + + + + + const accountLinkingOnly = document.getElementById("accountLinkingOnly"); + accountLinkingOnly.addEventListener("change", function () { + handleCheckboxValue(accountLinkingOnly); + + }); + + + const hideLoginPage = document.getElementById("hideLoginPage"); + hideLoginPage.addEventListener("change", function () { + handleCheckboxValue(hideLoginPage); + + }); + + + var SignatureAlgorithm = document.getElementById("SignatureAlgorithm"); + var SAMLSignatureKeyName = document.getElementById("SAMLSignatureKeyName"); + + const wantAuthnRequestsSigned = document.getElementById("wantAuthnRequestsSigned"); + wantAuthnRequestsSigned.addEventListener("change", function () { + if (wantAuthnRequestsSigned.checked) { + wantAuthnRequestsSigned.value = true; + SignatureAlgorithm.removeAttribute("disabled"); + SAMLSignatureKeyName.removeAttribute("disabled"); + encryption_algorithm.removeAttribute("disabled"); + + } + else { + wantAuthnRequestsSigned.value = false; + SignatureAlgorithm.setAttribute("disabled", "true"); + SAMLSignatureKeyName.setAttribute("disabled", "true"); + encryption_algorithm.setAttribute("disabled", "true"); + + + ; + } + }); + + const deleteButtonsClassRefs = document.querySelectorAll(".delete"); const addButtonClassRefs = document.getElementById("addClassRefs"); const ClassRefs_items = document.getElementById("ClassRefs_items"); - + deleteButtonsClassRefs.forEach(function (button) { button.style.display = "inline";}); - + addButtonClassRefs.addEventListener("click", function (e) { deleteButtonsClassRefs.forEach(function (button) { button.style.display = "inline"; }); - + const newItem = document.createElement("div"); newItem.className = "next-referral col-4"; newItem.innerHTML = ''; ClassRefs_items.appendChild(newItem); }); - + document.body.addEventListener("click", function (e) { if (e.target.classList.contains("delete")) { e.preventDefault(); @@ -240,39 +240,39 @@ wantAuthnRequestsSigned.addEventListener("change", function () { }); }); - const deleteButtonsDeclRefs = document.querySelectorAll(".delete1"); - const addButtonDeclRefs = document.getElementById("addDeclRefs"); - const DeclRefs_items = document.getElementById("DeclRefs_items"); +const deleteButtonsDeclRefs = document.querySelectorAll(".delete1"); +const addButtonDeclRefs = document.getElementById("addDeclRefs"); +const DeclRefs_items = document.getElementById("DeclRefs_items"); +deleteButtonsDeclRefs.forEach(function (button) { + button.style.display = "inline"; +}); + +addButtonDeclRefs.addEventListener("click", function (e) { deleteButtonsDeclRefs.forEach(function (button) { button.style.display = "inline"; }); + + const newItem = document.createElement("div"); + newItem.className = "next-referral col-4"; + newItem.innerHTML = ''; + DeclRefs_items.appendChild(newItem); +}); - addButtonDeclRefs.addEventListener("click", function (e) { - deleteButtonsDeclRefs.forEach(function (button) { - button.style.display = "inline"; - }); - - const newItem = document.createElement("div"); - newItem.className = "next-referral col-4"; - newItem.innerHTML = ''; - DeclRefs_items.appendChild(newItem); - }); - - document.body.addEventListener("click", function (e) { - if (e.target.classList.contains("delete1")) { - e.preventDefault(); - const items = DeclRefs_items.querySelectorAll(".next-referral"); - if (items.length > 0) { - items[items.length - 1].remove(); - deleteButtonsDeclRefs.forEach(function (button, index) { - if (index === items.length - 1) { - button.style.display = "inline"; - } - }); - } +document.body.addEventListener("click", function (e) { + if (e.target.classList.contains("delete1")) { + e.preventDefault(); + const items = DeclRefs_items.querySelectorAll(".next-referral"); + if (items.length > 0) { + items[items.length - 1].remove(); + deleteButtonsDeclRefs.forEach(function (button, index) { + if (index === items.length - 1) { + button.style.display = "inline"; + } + }); } - + } + }); @@ -284,8 +284,8 @@ validateSignatures.addEventListener("change", function () { if (validateSignatures.checked) { validateSignatures.value = true; additionalField1.removeAttribute("disabled"); - - + + } else { validateSignatures.value = false; @@ -298,39 +298,31 @@ var Artifact_Resolution = document.getElementById("Artifact_Resolution"); Artifact_Resolution.addEventListener("change", function () { - if (Artifact_Resolution.checked) { - Artifact_Resolution.value = true; - additionalField_endpoint.removeAttribute("disabled"); - - } - else { - Artifact_Resolution.value = false; - additionalField_endpoint.setAttribute("disabled", "true"); - additionalField_endpoint.value = ''; - ; - } -} + if (Artifact_Resolution.checked) { + Artifact_Resolution.value = true; + additionalField_endpoint.removeAttribute("disabled"); + + } + else { + Artifact_Resolution.value = false; + additionalField_endpoint.setAttribute("disabled", "true"); + additionalField_endpoint.value = ''; + ; + } + } ); const Sign_Artifact_Resolution_Request = document.getElementById("Sign_Artifact_Resolution_Request"); Sign_Artifact_Resolution_Request.addEventListener("change", function () { handleCheckboxValue(Sign_Artifact_Resolution_Request); - + }); -const ArtifactResolution_via_HTTP_ARTIFACT = document.getElementById("ArtifactResolution_via_HTTP_ARTIFACT"); -ArtifactResolution_via_HTTP_ARTIFACT.addEventListener("change", function () { - handleCheckboxValue(ArtifactResolution_via_HTTP_ARTIFACT); - -}); - - - const Artifact_Resolution_with_SOAP = document.getElementById("Artifact_Resolution_with_SOAP"); Artifact_Resolution_with_SOAP.addEventListener("change", function () { handleCheckboxValue(Artifact_Resolution_with_SOAP); - + }); @@ -338,7 +330,7 @@ Artifact_Resolution_with_SOAP.addEventListener("change", function () { const Artifact_Resolution_with_XML_header = document.getElementById("Artifact_Resolution_with_XML_header"); Artifact_Resolution_with_XML_header.addEventListener("change", function () { handleCheckboxValue(Artifact_Resolution_with_XML_header); - + }); @@ -350,11 +342,11 @@ Mutual_TLS.addEventListener("change", function () { principalType_input.addEventListener('change', function () { if (principalType_input.value == "ATTRIBUTE" || principalType_input.value == "FRIENDLY_ATTRIBUTE") { principalAttribute_input.removeAttribute("disabled"); - + } else { principalAttribute_input.value = ''; principalAttribute_input.setAttribute("disabled", "true"); - + } - + }); diff --git a/src/main/resources/saml-extended-frontend/js/CheckBoxControllerEditProvider.js b/src/main/resources/saml-extended-frontend/js/CheckBoxControllerEditProvider.js index 1ef3631..26822ce 100644 --- a/src/main/resources/saml-extended-frontend/js/CheckBoxControllerEditProvider.js +++ b/src/main/resources/saml-extended-frontend/js/CheckBoxControllerEditProvider.js @@ -1,368 +1,356 @@ document.addEventListener('DOMContentLoaded', function() { -storedData = localStorage.getItem('pluginData'); -var pluginData = JSON.parse(storedData); -backchannel.value = pluginData.config.backchannelSupported ? pluginData.config.backchannelSupported : false; -backchannel.addEventListener("change", function () { - handleCheckboxValue(backchannel); -}); - - -const allowCreate = document.getElementById("allowCreate"); -allowCreate.value = pluginData.config.allowCreate ? pluginData.config.allowCreate : false; -allowCreate.addEventListener("change", function () { - handleCheckboxValue(allowCreate); -}); - - - - -const httpPostBindingResponse = document.getElementById("httpPostBindingResponse"); -httpPostBindingResponse.value = pluginData.config.postBindingResponse ? pluginData.config.postBindingResponse : false; -httpPostBindingResponse.addEventListener("change", function () { - handleCheckboxValue(httpPostBindingResponse); - - -}); - - - - - - -const httpPostBindingAuthnRequest = document.getElementById("httpPostBindingAuthnRequest"); -httpPostBindingAuthnRequest.value = pluginData.config.postBindingAuthnRequest ? pluginData.config.postBindingAuthnRequest : false; -httpPostBindingAuthnRequest.addEventListener("change", function () { - handleCheckboxValue(httpPostBindingAuthnRequest); - -}); - -const httpPostBindingLogout = document.getElementById("httpPostBindingLogout"); -httpPostBindingLogout.value = pluginData.config.postBindingLogout ? pluginData.config.postBindingLogout : false; -httpPostBindingLogout.addEventListener("change", function () { - handleCheckboxValue(httpPostBindingLogout); - -}); - - -const wantAssertionsSigned = document.getElementById("wantAssertionsSigned"); -wantAssertionsSigned.value = pluginData.config.wantAssertionsSigned ? pluginData.config.wantAssertionsSigned : false; -wantAssertionsSigned.addEventListener("change", function () { - handleCheckboxValue(wantAssertionsSigned); - -}); - - -const wantAssertionsEncrypted = document.getElementById("wantAssertionsEncrypted"); -wantAssertionsEncrypted.value = pluginData.config.wantAssertionsEncrypted ? pluginData.config.wantAssertionsEncrypted : false; -wantAssertionsEncrypted.addEventListener("change", function () { - handleCheckboxValue(wantAssertionsEncrypted); - -}); - - -const forceAuthentication = document.getElementById("forceAuthentication"); -forceAuthentication.value = pluginData.config.forceAuthn ? pluginData.config.forceAuthn : false; -forceAuthentication.addEventListener("change", function () { - handleCheckboxValue(forceAuthentication); -}); - - - -const signMetadata = document.getElementById("signMetadata"); -signMetadata.value = pluginData.config.signSpMetadata ? pluginData.config.signSpMetadata : false -signMetadata.addEventListener("change", function () { - handleCheckboxValue(signMetadata); - -}); - - -const passSubject = document.getElementById("passSubject"); -passSubject.value = pluginData.config.loginHint ? pluginData.config.loginHint : false; -passSubject.addEventListener("change", function () { - handleCheckboxValue(passSubject); - -}); - - -const storeToken = document.getElementById("storeToken"); -storeToken.value = pluginData.storeToken ? pluginData.storeToken : false; -storeToken.addEventListener("change", function () { - handleCheckboxValue(storeToken); - -}); - - -const storedTokensReadable = document.getElementById("storedTokensReadable"); -storedTokensReadable.value = pluginData.addReadTokenRoleOnCreate ? pluginData.addReadTokenRoleOnCreate : false; -storedTokensReadable.addEventListener("change", function () { - handleCheckboxValue(storedTokensReadable); - -}); - + storedData = localStorage.getItem('pluginData'); + var pluginData = JSON.parse(storedData); + backchannel.value = pluginData.config.backchannelSupported ? pluginData.config.backchannelSupported : false; + backchannel.addEventListener("change", function () { + handleCheckboxValue(backchannel); + }); + + + const allowCreate = document.getElementById("allowCreate"); + allowCreate.value = pluginData.config.allowCreate ? pluginData.config.allowCreate : false; + allowCreate.addEventListener("change", function () { + handleCheckboxValue(allowCreate); + }); + + const httpPostBindingResponse = document.getElementById("httpPostBindingResponse"); + httpPostBindingResponse.value = pluginData.config.postBindingResponse ? pluginData.config.postBindingResponse : false; + httpPostBindingResponse.addEventListener("change", function () { + handleCheckboxValue(httpPostBindingResponse); + }); + + const artifactBindingResponse = document.getElementById("artifactBindingResponse"); + artifactBindingResponse.checked = pluginData.config.artifactBindingResponse === 'true'; + artifactBindingResponse.value = artifactBindingResponse.checked; + artifactBindingResponse.addEventListener("change", function () { + handleCheckboxValue(artifactBindingResponse); + }); + + const httpPostBindingAuthnRequest = document.getElementById("httpPostBindingAuthnRequest"); + httpPostBindingAuthnRequest.value = pluginData.config.postBindingAuthnRequest ? pluginData.config.postBindingAuthnRequest : false; + httpPostBindingAuthnRequest.addEventListener("change", function () { + handleCheckboxValue(httpPostBindingAuthnRequest); + + }); + + const httpPostBindingLogout = document.getElementById("httpPostBindingLogout"); + httpPostBindingLogout.value = pluginData.config.postBindingLogout ? pluginData.config.postBindingLogout : false; + httpPostBindingLogout.addEventListener("change", function () { + handleCheckboxValue(httpPostBindingLogout); + + }); + + + const wantAssertionsSigned = document.getElementById("wantAssertionsSigned"); + wantAssertionsSigned.value = pluginData.config.wantAssertionsSigned ? pluginData.config.wantAssertionsSigned : false; + wantAssertionsSigned.addEventListener("change", function () { + handleCheckboxValue(wantAssertionsSigned); + + }); + + + const wantAssertionsEncrypted = document.getElementById("wantAssertionsEncrypted"); + wantAssertionsEncrypted.value = pluginData.config.wantAssertionsEncrypted ? pluginData.config.wantAssertionsEncrypted : false; + wantAssertionsEncrypted.addEventListener("change", function () { + handleCheckboxValue(wantAssertionsEncrypted); + + }); + + + const forceAuthentication = document.getElementById("forceAuthentication"); + forceAuthentication.value = pluginData.config.forceAuthn ? pluginData.config.forceAuthn : false; + forceAuthentication.addEventListener("change", function () { + handleCheckboxValue(forceAuthentication); + }); + + + + const signMetadata = document.getElementById("signMetadata"); + signMetadata.value = pluginData.config.signSpMetadata ? pluginData.config.signSpMetadata : false + signMetadata.addEventListener("change", function () { + handleCheckboxValue(signMetadata); + + }); + + + const passSubject = document.getElementById("passSubject"); + passSubject.value = pluginData.config.loginHint ? pluginData.config.loginHint : false; + passSubject.addEventListener("change", function () { + handleCheckboxValue(passSubject); + + }); + + + const storeToken = document.getElementById("storeToken"); + storeToken.value = pluginData.storeToken ? pluginData.storeToken : false; + storeToken.addEventListener("change", function () { + handleCheckboxValue(storeToken); + + }); + + + const storedTokensReadable = document.getElementById("storedTokensReadable"); + storedTokensReadable.value = pluginData.addReadTokenRoleOnCreate ? pluginData.addReadTokenRoleOnCreate : false; + storedTokensReadable.addEventListener("change", function () { + handleCheckboxValue(storedTokensReadable); + + }); + const id_token_hint=document.getElementById("id_token_hint"); id_token_hint.value = pluginData.config.sendIdTokenOnLogout ? pluginData.config.sendIdTokenOnLogout : false; id_token_hint.addEventListener("change", function () { handleCheckboxValue(id_token_hint); }); - -const client_id_in_logout_requests=document.getElementById("client_id_in_logout_requests") -client_id_in_logout_requests.value = pluginData.config.sendClientIdOnLogout ? pluginData.config.sendClientIdOnLogout : false; -client_id_in_logout_requests.addEventListener("change", function () { - handleCheckboxValue(client_id_in_logout_requests); - -}); - -const trustEmail = document.getElementById("trustEmail"); -trustEmail.value = pluginData.trustEmail ? pluginData.trustEmail : false; -trustEmail.addEventListener("change", function () { - handleCheckboxValue(trustEmail); - -}); - - - - -const accountLinkingOnly = document.getElementById("accountLinkingOnly"); -accountLinkingOnly.value = pluginData.linkOnly ? pluginData.linkOnly : false; -accountLinkingOnly.addEventListener("change", function () { - handleCheckboxValue(accountLinkingOnly); - -}); - - -const hideLoginPage = document.getElementById("hideLoginPage"); -hideLoginPage.value = pluginData.config.hideOnLoginPage ? pluginData.config.hideOnLoginPage : false; -hideLoginPage.addEventListener("change", function () { - handleCheckboxValue(hideLoginPage); - -}); - - -var SignatureAlgorithm = document.getElementById("SignatureAlgorithm"); -var SAMLSignatureKeyName = document.getElementById("SAMLSignatureKeyName"); - -const wantAuthnRequestsSigned = document.getElementById("wantAuthnRequestsSigned"); -wantAuthnRequestsSigned.value = pluginData.config.wantAuthnRequestsSigned ? pluginData.config.wantAuthnRequestsSigned : false; -wantAuthnRequestsSigned.addEventListener("change", function () { - if (wantAuthnRequestsSigned.checked) { - wantAuthnRequestsSigned.value = true; - SignatureAlgorithm.removeAttribute("disabled"); - SAMLSignatureKeyName.removeAttribute("disabled"); - encryption_algorithm.removeAttribute("disabled"); - - } - else { - wantAuthnRequestsSigned.value = false; - SignatureAlgorithm.setAttribute("disabled", "true"); - SAMLSignatureKeyName.setAttribute("disabled", "true"); - encryption_algorithm.setAttribute("disabled", "true"); - - - ; - } -}); - -const ArtifactResolutionService_in_metadata = document.getElementById("ArtifactResolutionService_in_metadata"); -ArtifactResolutionService_in_metadata.value = pluginData.config.includeArtifactResolutionServiceMetadata ? pluginData.config.includeArtifactResolutionServiceMetadata : false; -ArtifactResolutionService_in_metadata.addEventListener("change", function () { - handleCheckboxValue(ArtifactResolutionService_in_metadata); - -}); - -document.addEventListener("DOMContentLoaded", function () { - const deleteButtonsClassRefs = document.querySelectorAll(".delete"); - const addButtonClassRefs = document.getElementById("addClassRefs"); - const ClassRefs_items = document.getElementById("ClassRefs_items"); - - deleteButtonsClassRefs.forEach(function (button) { - button.style.display = "inline"; + + const client_id_in_logout_requests=document.getElementById("client_id_in_logout_requests") + client_id_in_logout_requests.value = pluginData.config.sendClientIdOnLogout ? pluginData.config.sendClientIdOnLogout : false; + client_id_in_logout_requests.addEventListener("change", function () { + handleCheckboxValue(client_id_in_logout_requests); + }); - - addButtonClassRefs.addEventListener("click", function (e) { + + const trustEmail = document.getElementById("trustEmail"); + trustEmail.value = pluginData.trustEmail ? pluginData.trustEmail : false; + trustEmail.addEventListener("change", function () { + handleCheckboxValue(trustEmail); + + }); + + + + + const accountLinkingOnly = document.getElementById("accountLinkingOnly"); + accountLinkingOnly.value = pluginData.linkOnly ? pluginData.linkOnly : false; + accountLinkingOnly.addEventListener("change", function () { + handleCheckboxValue(accountLinkingOnly); + + }); + + + const hideLoginPage = document.getElementById("hideLoginPage"); + hideLoginPage.value = pluginData.hideOnLogin ? pluginData.hideOnLogin : false; + hideLoginPage.addEventListener("change", function () { + handleCheckboxValue(hideLoginPage); + + }); + + + var SignatureAlgorithm = document.getElementById("SignatureAlgorithm"); + var SAMLSignatureKeyName = document.getElementById("SAMLSignatureKeyName"); + + const wantAuthnRequestsSigned = document.getElementById("wantAuthnRequestsSigned"); + wantAuthnRequestsSigned.value = pluginData.config.wantAuthnRequestsSigned ? pluginData.config.wantAuthnRequestsSigned : false; + wantAuthnRequestsSigned.addEventListener("change", function () { + if (wantAuthnRequestsSigned.checked) { + wantAuthnRequestsSigned.value = true; + SignatureAlgorithm.removeAttribute("disabled"); + SAMLSignatureKeyName.removeAttribute("disabled"); + encryption_algorithm.removeAttribute("disabled"); + + } + else { + wantAuthnRequestsSigned.value = false; + SignatureAlgorithm.setAttribute("disabled", "true"); + SAMLSignatureKeyName.setAttribute("disabled", "true"); + encryption_algorithm.setAttribute("disabled", "true"); + + + ; + } + }); + + const ArtifactResolutionService_in_metadata = document.getElementById("ArtifactResolutionService_in_metadata"); + ArtifactResolutionService_in_metadata.value = pluginData.config.includeArtifactResolutionServiceMetadata ? pluginData.config.includeArtifactResolutionServiceMetadata : false; + ArtifactResolutionService_in_metadata.addEventListener("change", function () { + handleCheckboxValue(ArtifactResolutionService_in_metadata); + + }); + + document.addEventListener("DOMContentLoaded", function () { + const deleteButtonsClassRefs = document.querySelectorAll(".delete"); + const addButtonClassRefs = document.getElementById("addClassRefs"); + const ClassRefs_items = document.getElementById("ClassRefs_items"); + deleteButtonsClassRefs.forEach(function (button) { button.style.display = "inline"; }); - - const newItem = document.createElement("div"); - newItem.className = "next-referral col-4"; - newItem.innerHTML = ''; - ClassRefs_items.appendChild(newItem); - }); - - document.body.addEventListener("click", function (e) { - if (e.target.classList.contains("delete")) { - const items = ClassRefs_items.querySelectorAll(".next-referral"); - if (items.length > 0) { - items[items.length - 1].remove(); - deleteButtonsClassRefs.forEach(function (button, index) { - if (index === items.length - 1) { - button.style.display = "inline"; - } - }); + + addButtonClassRefs.addEventListener("click", function (e) { + deleteButtonsClassRefs.forEach(function (button) { + button.style.display = "inline"; + }); + + const newItem = document.createElement("div"); + newItem.className = "next-referral col-4"; + newItem.innerHTML = ''; + ClassRefs_items.appendChild(newItem); + }); + + document.body.addEventListener("click", function (e) { + if (e.target.classList.contains("delete")) { + const items = ClassRefs_items.querySelectorAll(".next-referral"); + if (items.length > 0) { + items[items.length - 1].remove(); + deleteButtonsClassRefs.forEach(function (button, index) { + if (index === items.length - 1) { + button.style.display = "inline"; + } + }); + } } - } - }); -}); - -document.addEventListener("DOMContentLoaded", function () { - const deleteButtonsDeclRefs = document.querySelectorAll(".delete1"); - const addButtonDeclRefs = document.getElementById("addDeclRefs"); - const DeclRefs_items = document.getElementById("DeclRefs_items"); - - deleteButtonsDeclRefs.forEach(function (button) { - button.style.display = "inline"; + }); }); - - addButtonDeclRefs.addEventListener("click", function (e) { + + document.addEventListener("DOMContentLoaded", function () { + const deleteButtonsDeclRefs = document.querySelectorAll(".delete1"); + const addButtonDeclRefs = document.getElementById("addDeclRefs"); + const DeclRefs_items = document.getElementById("DeclRefs_items"); + deleteButtonsDeclRefs.forEach(function (button) { button.style.display = "inline"; }); - - const newItem = document.createElement("div"); - newItem.className = "next-referral col-4"; - newItem.innerHTML = ''; - DeclRefs_items.appendChild(newItem); - }); - - document.body.addEventListener("click", function (e) { - if (e.target.classList.contains("delete1")) { - const items = DeclRefs_items.querySelectorAll(".next-referral"); - if (items.length > 0) { - items[items.length - 1].remove(); - deleteButtonsDeclRefs.forEach(function (button, index) { - if (index === items.length - 1) { - button.style.display = "inline"; - } - }); + + addButtonDeclRefs.addEventListener("click", function (e) { + deleteButtonsDeclRefs.forEach(function (button) { + button.style.display = "inline"; + }); + + const newItem = document.createElement("div"); + newItem.className = "next-referral col-4"; + newItem.innerHTML = ''; + DeclRefs_items.appendChild(newItem); + }); + + document.body.addEventListener("click", function (e) { + if (e.target.classList.contains("delete1")) { + const items = DeclRefs_items.querySelectorAll(".next-referral"); + if (items.length > 0) { + items[items.length - 1].remove(); + deleteButtonsDeclRefs.forEach(function (button, index) { + if (index === items.length - 1) { + button.style.display = "inline"; + } + }); + } } - } + }); }); -}); - - - -var validateSignatures = document.getElementById("validateSignatures"); -var additionalField1 = document.getElementById("ValidatingX509Certificates"); -var saml_EntityDescriptor=document.getElementById("saml_EntityDescriptor") -var Use_Metadata_Descriptor_URL=document.getElementById("Use_Metadata_Descriptor_URL") -validateSignatures.value = pluginData.config.validateSignature ? pluginData.config.validateSignature : false; + + + + var validateSignatures = document.getElementById("validateSignatures"); + var additionalField1 = document.getElementById("ValidatingX509Certificates"); + var saml_EntityDescriptor=document.getElementById("saml_EntityDescriptor") + var Use_Metadata_Descriptor_URL=document.getElementById("Use_Metadata_Descriptor_URL") + validateSignatures.value = pluginData.config.validateSignature ? pluginData.config.validateSignature : false; var validateSignatures = document.getElementById("validateSignatures"); var additionalField1 = document.getElementById("ValidatingX509Certificates"); var saml_EntityDescriptor = document.getElementById("saml_EntityDescriptor"); var Use_Metadata_Descriptor_URL = document.getElementById("Use_Metadata_Descriptor_URL"); - validateSignatures.checked = pluginData.config.validateSignature ? pluginData.config.validateSignature : false; - validateSignatures.addEventListener("change", function () { - if (validateSignatures.checked) { - validateSignatures.value = true; - additionalField1.removeAttribute("disabled"); - saml_EntityDescriptor.style.display = 'block'; - Use_Metadata_Descriptor_URL.style.display = 'block'; - } else { - additionalField1.setAttribute("disabled", "true"); - additionalField1.value = ''; - saml_EntityDescriptor.style.display = 'none'; - Use_Metadata_Descriptor_URL.style.display = 'none'; - validateSignatures.value = false; - } - }); - - validateSignatures.dispatchEvent(new Event("change")); - + validateSignatures.checked = pluginData.config.validateSignature ? pluginData.config.validateSignature : false; + validateSignatures.addEventListener("change", function () { + if (validateSignatures.checked) { + validateSignatures.value = true; + additionalField1.removeAttribute("disabled"); + saml_EntityDescriptor.style.display = 'block'; + Use_Metadata_Descriptor_URL.style.display = 'block'; + } else { + additionalField1.setAttribute("disabled", "true"); + additionalField1.value = ''; + saml_EntityDescriptor.style.display = 'none'; + Use_Metadata_Descriptor_URL.style.display = 'none'; + validateSignatures.value = false; + } + }); + + validateSignatures.dispatchEvent(new Event("change")); + var UseMetadataDescriptorURL = document.getElementById("UseMetadataDescriptorURL"); var Validating_X509_Certificates=document.getElementById("Validating_X509_Certificates"); UseMetadataDescriptorURL.checked = pluginData.config.useMetadataDescriptorUrl ? pluginData.config.useMetadataDescriptorUrl : false; UseMetadataDescriptorURL.addEventListener("change", function () { - if (UseMetadataDescriptorURL.checked) { - UseMetadataDescriptorURL.value = true; - Validating_X509_Certificates.style.display='none' - } - else { - UseMetadataDescriptorURL.value = false; - Validating_X509_Certificates.style.display='block' - ; - } - } - + if (UseMetadataDescriptorURL.checked) { + UseMetadataDescriptorURL.value = true; + Validating_X509_Certificates.style.display='none' + } + else { + UseMetadataDescriptorURL.value = false; + Validating_X509_Certificates.style.display='block' + ; + } + } + ); - - -var Artifact_Resolution = document.getElementById("Artifact_Resolution"); -Artifact_Resolution.value = pluginData.config.artifactResolution ? pluginData.config.artifactResolution : false; - -Artifact_Resolution.addEventListener("change", function () { - if (Artifact_Resolution.checked) { - Artifact_Resolution.value = true; - additionalField_endpoint.removeAttribute("disabled"); - - } - else { - Artifact_Resolution.value = false; - additionalField_endpoint.setAttribute("disabled", "true"); - additionalField_endpoint.value = ''; - - ; - } -} -); - - -const Sign_Artifact_Resolution_Request = document.getElementById("Sign_Artifact_Resolution_Request"); -Sign_Artifact_Resolution_Request.value = pluginData.config.signArtifactResolutionRequest ? pluginData.config.signArtifactResolutionRequest : false; -Sign_Artifact_Resolution_Request.addEventListener("change", function () { - handleCheckboxValue(Sign_Artifact_Resolution_Request); - -}); - -const ArtifactResolution_via_HTTP_ARTIFACT = document.getElementById("ArtifactResolution_via_HTTP_ARTIFACT"); -ArtifactResolution_via_HTTP_ARTIFACT.value = pluginData.config.artifactResolutionHTTPArtifact ? pluginData.config.artifactResolutionHTTPArtifact : false; -ArtifactResolution_via_HTTP_ARTIFACT.addEventListener("change", function () { - handleCheckboxValue(ArtifactResolution_via_HTTP_ARTIFACT); - -}); - - - - -const Artifact_Resolution_with_SOAP = document.getElementById("Artifact_Resolution_with_SOAP"); -Artifact_Resolution_with_SOAP.value = pluginData.config.artifactResolutionSOAP ? pluginData.config.artifactResolutionSOAP : false; -Artifact_Resolution_with_SOAP.addEventListener("change", function () { - handleCheckboxValue(Artifact_Resolution_with_SOAP); - -}); - - - -const Artifact_Resolution_with_XML_header = document.getElementById("Artifact_Resolution_with_XML_header"); -Artifact_Resolution_with_XML_header.value = pluginData.config.artifactResolutionWithXmlHeader ? pluginData.config.artifactResolutionWithXmlHeader : false; -Artifact_Resolution_with_XML_header.addEventListener("change", function () { - handleCheckboxValue(Artifact_Resolution_with_XML_header); - -}); - - -const Mutual_TLS = document.getElementById("Mutual_TLS"); -Mutual_TLS.value = pluginData.config.mutualTls ? pluginData.config.mutualTls : false; -Mutual_TLS.addEventListener("change", function () { - handleCheckboxValue(Mutual_TLS); - -}); -const enabled = document.getElementById("enabled"); -enabled.value = pluginData.enabled ? pluginData.enabled : false; -enabled.addEventListener("change", function () { - handleCheckboxValue(enabled); - -}); - -principalType_input.addEventListener('change', function () { - if (principalType_input.value == "ATTRIBUTE" || principalType_input.value == "FRIENDLY_ATTRIBUTE") { - principalAttribute_input.removeAttribute("disabled"); - - } else { - principalAttribute_input.value = ''; - principalAttribute_input.setAttribute("disabled", "true"); - - } -}) ; + + + var Artifact_Resolution = document.getElementById("Artifact_Resolution"); + Artifact_Resolution.value = pluginData.config.artifactResolution ? pluginData.config.artifactResolution : false; + + Artifact_Resolution.addEventListener("change", function () { + if (Artifact_Resolution.checked) { + Artifact_Resolution.value = true; + additionalField_endpoint.removeAttribute("disabled"); + + } + else { + Artifact_Resolution.value = false; + additionalField_endpoint.setAttribute("disabled", "true"); + additionalField_endpoint.value = ''; + + ; + } + } + ); + + + const Sign_Artifact_Resolution_Request = document.getElementById("Sign_Artifact_Resolution_Request"); + Sign_Artifact_Resolution_Request.value = pluginData.config.signArtifactResolutionRequest ? pluginData.config.signArtifactResolutionRequest : false; + Sign_Artifact_Resolution_Request.addEventListener("change", function () { + handleCheckboxValue(Sign_Artifact_Resolution_Request); + + }); + + + const Artifact_Resolution_with_SOAP = document.getElementById("Artifact_Resolution_with_SOAP"); + Artifact_Resolution_with_SOAP.value = pluginData.config.artifactResolutionSOAP ? pluginData.config.artifactResolutionSOAP : false; + Artifact_Resolution_with_SOAP.addEventListener("change", function () { + handleCheckboxValue(Artifact_Resolution_with_SOAP); + + }); + + + + const Artifact_Resolution_with_XML_header = document.getElementById("Artifact_Resolution_with_XML_header"); + Artifact_Resolution_with_XML_header.value = pluginData.config.artifactResolutionWithXmlHeader ? pluginData.config.artifactResolutionWithXmlHeader : false; + Artifact_Resolution_with_XML_header.addEventListener("change", function () { + handleCheckboxValue(Artifact_Resolution_with_XML_header); + + }); + + + const Mutual_TLS = document.getElementById("Mutual_TLS"); + Mutual_TLS.value = pluginData.config.mutualTls ? pluginData.config.mutualTls : false; + Mutual_TLS.addEventListener("change", function () { + handleCheckboxValue(Mutual_TLS); + + }); + const enabled = document.getElementById("enabled"); + enabled.value = pluginData.enabled ? pluginData.enabled : false; + enabled.addEventListener("change", function () { + handleCheckboxValue(enabled); + + }); + + principalType_input.addEventListener('change', function () { + if (principalType_input.value == "ATTRIBUTE" || principalType_input.value == "FRIENDLY_ATTRIBUTE") { + principalAttribute_input.removeAttribute("disabled"); + + } else { + principalAttribute_input.value = ''; + principalAttribute_input.setAttribute("disabled", "true"); + + } + }) ; }); \ No newline at end of file diff --git a/src/main/resources/saml-extended-frontend/js/Config.js b/src/main/resources/saml-extended-frontend/js/Config.js index d0d56df..af1ac53 100644 --- a/src/main/resources/saml-extended-frontend/js/Config.js +++ b/src/main/resources/saml-extended-frontend/js/Config.js @@ -1,11 +1,12 @@ -const ServerUrl = window.location.protocol+"//" + window.location.host; +const relativePath = window.location.pathname.substring(0,window.location.pathname.indexOf("/realm")); +const serverUrl = window.location.protocol+"//" + window.location.host + relativePath; const clientid = 'saml-extended'; -const postLogoutRedirect = `${ServerUrl}/realms/master/samlconfig/pages/realm`; -const redirectUri = `${ServerUrl}/realms/master/samlconfig/pages/list`; -const editprovider=`${ServerUrl}/realms/master/samlconfig/pages/editprovider`; -const addprovider=`${ServerUrl}/realms/master/samlconfig/pages/addprovider`; +const postLogoutRedirect = `${serverUrl}/realms/master/samlconfig/pages/realm`; +const redirectUri = `${serverUrl}/realms/master/samlconfig/pages/list`; +const editprovider=`${serverUrl}/realms/master/samlconfig/pages/editprovider`; +const addprovider=`${serverUrl}/realms/master/samlconfig/pages/addprovider`; const realm = localStorage.getItem('realm_input'); -localStorage.setItem('ServerUrl', ServerUrl); +localStorage.setItem('serverUrl', serverUrl); localStorage.setItem('postLogoutRedirect', postLogoutRedirect); localStorage.setItem('redirectUri', redirectUri); localStorage.setItem('addprovider', addprovider); diff --git a/src/main/resources/saml-extended-frontend/js/EditProvider.js b/src/main/resources/saml-extended-frontend/js/EditProvider.js index a31dca0..2a1d691 100644 --- a/src/main/resources/saml-extended-frontend/js/EditProvider.js +++ b/src/main/resources/saml-extended-frontend/js/EditProvider.js @@ -3,7 +3,7 @@ edit.addEventListener('click', () => { keycloak.updateToken(300).then((bool) => { if (bool) { newAccessToken = keycloak.token; - + var authnContextClassRefs = [] const ClassRefs_inputs = ClassRefs_items.querySelectorAll("input"); ClassRefs_inputs.forEach(input => { @@ -18,7 +18,7 @@ edit.addEventListener('click', () => { authnContextDeclRefs.push(input.value); } }); - + var Single_Sign_On_Service_URL = Single_Sign_On_Service_URL_input.value; var Single_Logout_Service_URL = Single_Logout_Service_URL_input.value; var nameIdPolicy = nameIdPolicy_input.value; @@ -29,19 +29,21 @@ edit.addEventListener('click', () => { "alias": alias, "displayName": Display_Name_input.value, "providerId": "saml-extended", - "enabled": "true", + "enabled": String(enabled.checked), "updateProfileFirstLoginMode": "on", "trustEmail": trustEmail.value, "storeToken": storeToken.value, "addReadTokenRoleOnCreate": storedTokensReadable.value, "authenticateByDefault": "false", "linkOnly": accountLinkingOnly.value, + "hideOnLogin": hideLoginPage.value, "firstBrokerLoginFlowAlias": firstLoginFlow_input.value, "postBrokerLoginFlowAlias": postLoginFlow_input.value, config: { "postBindingLogout": httpPostBindingLogout.value, "authnContextClassRefs": authnContextClassRefs.length > 0 ? JSON.stringify(authnContextClassRefs) : undefined, "postBindingResponse": httpPostBindingResponse.value, + "artifactBindingResponse": artifactBindingResponse.value, "singleLogoutServiceUrl": Single_Logout_Service_URL, "authnContextDeclRefs": authnContextDeclRefs.length > 0 ? JSON.stringify(authnContextDeclRefs) : undefined, "backchannelSupported": backchannel.value, @@ -57,7 +59,6 @@ edit.addEventListener('click', () => { "allowedClockSkew": allowedClockSkew_input.value, "guiOrder": Display_Order_input.value, "validateSignature": validateSignatures.value, - "hideOnLoginPage": hideLoginPage.value, "signingCertificate": ValidatingX509Certificates_input.value, "nameIDPolicyFormat": nameIdPolicy1, "entityId": Service_Provider_Entity_ID_input.value, @@ -68,6 +69,7 @@ edit.addEventListener('click', () => { "wantAssertionsSigned": wantAssertionsSigned.value, "postBindingAuthnRequest": httpPostBindingAuthnRequest.value, "forceAuthn": forceAuthentication.value, + "assertionConsumingServiceIndex": assertionConsumingServiceIndex_input.value, "attributeConsumingServiceIndex": attributeConsumingServiceIndex_input.value, "principalType": principalType_input.value, "principalAttribute": principalAttribute_input.value, @@ -77,7 +79,6 @@ edit.addEventListener('click', () => { "signArtifactResolutionRequest": Sign_Artifact_Resolution_Request.value, "artifactResolutionSOAP": Artifact_Resolution_with_SOAP.value, "artifactResolutionWithXmlHeader": Artifact_Resolution_with_XML_header.value, - "artifactResolutionHTTPArtifact": ArtifactResolution_via_HTTP_ARTIFACT.value, "mutualTls": Mutual_TLS.value, "charSet": CharacterSet_input.value, "metadataValidUntilUnit": Metadata_expires_in_input.value, @@ -88,28 +89,28 @@ edit.addEventListener('click', () => { "metadataDescriptorUrl":samlEntityDescriptor_input.value, "useMetadataDescriptorUrl":UseMetadataDescriptorURL.value, "attributeConsumingServiceMetadata":attributeServicesArray.length > 0 ? JSON.stringify(attributeServicesArray) : undefined - + } }; - - + + let isValid = true; hasFocused = false; - + if (!Single_Sign_On_Service_URL_input.value || !Single_Sign_On_Service_URL_input.value.startsWith("https://")) { handleInvalidInput(Single_Sign_On_Service_URL_input, errorMessage_URL, "Enter a valid URL"); isValid = false; } else { handleValidInput(Single_Sign_On_Service_URL_input, errorMessage_URL,""); } - + if (Single_Logout_Service_URL_input.value && !Single_Logout_Service_URL_input.value.startsWith("https://")) { handleInvalidInput(Single_Logout_Service_URL_input, errorMessage_URL_logout, "Enter a valid URL"); isValid = false; } else { handleValidInput(Single_Logout_Service_URL_input, errorMessage_URL_logout,""); } - + if (UseMetadataDescriptorURL.checked) { if (!samlEntityDescriptor_input.value ||!samlEntityDescriptor_input.value.startsWith("https://")) { handleInvalidInput(samlEntityDescriptor_input, samlEntityDescriptor_errorMessage_URL, "Enter a valid URL!"); @@ -118,17 +119,17 @@ edit.addEventListener('click', () => { else { handleValidInput(samlEntityDescriptor_input, samlEntityDescriptor_errorMessage_URL,""); } - - + + } - + if (!isValid) { return; } - - + + removeEmptyStrings(data); - + const configKeys = Object.keys(data.config); for (const key of configKeys) { if (typeof data.config[key] === 'string' && data.config[key].trim() === "") { @@ -138,102 +139,98 @@ edit.addEventListener('click', () => { if (Array.isArray(data.config.authnContextClassRefs) && data.config.authnContextClassRefs.length === 0) { delete data.config.authnContextClassRefs; } - + if (Array.isArray(data.config.authnContextDeclRefs) && data.config.authnContextDeclRefs.length === 0) { delete data.config.authnContextDeclRefs; } - - - + + + var selectedrealm = localStorage.getItem('selectedRealm'); - if(alias_input.value){ - // Sending a GET request to check if the plugin exists - fetch(`${ServerUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${alias_input.value}`, { - method: 'GET', - headers: { - 'Authorization': `Bearer ${newAccessToken}`, - }, - }) - - // Handling the response of the GET request - .then(async checkPluginResponse => { - if (checkPluginResponse.ok) { - var pluginData = await checkPluginResponse.json(); - const updatePluginResponse = await fetch(`${ServerUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${alias_input.value}`, { - method: 'PUT', - headers: { - 'Authorization': `Bearer ${newAccessToken}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - } - - ); - localStorage.setItem('pluginData', JSON.stringify(data)); - - - - // Checking the response status for success - if (updatePluginResponse.status === 204 || updatePluginResponse.status === 201) { - console.log("Plugin updated successfully."); - alert("Plugin updated successfully."); - getAllPlugins(newAccessToken,selectedrealm); - localStorage.setItem('pluginData', JSON.stringify(data)); - - - } else { - console.error(`Failed to update/add the plugin. Response: ${updatePluginResponse.statusText}`); - console.error("Error Details:", await updatePluginResponse.json()); - alert("Failed to update the plugin") - } - } else if (checkPluginResponse.status === 404) { - // If the status is 404, the plugin does not exist, so send a POST request - return fetch(`${ServerUrl}/admin/realms/${selectedrealm}/identity-provider/instances`, { - method: 'POST', - headers: { - 'Authorization': `Bearer ${newAccessToken}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - }) + if(alias_input.value){ + // Sending a GET request to check if the plugin exists + fetch(`${serverUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${alias_input.value}`, { + method: 'GET', + headers: { + 'Authorization': `Bearer ${newAccessToken}`, + }, + }) + + // Handling the response of the GET request + .then(async checkPluginResponse => { + if (checkPluginResponse.ok) { + var pluginData = await checkPluginResponse.json(); + const updatePluginResponse = await fetch(`${serverUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${alias_input.value}`, { + method: 'PUT', + headers: { + 'Authorization': `Bearer ${newAccessToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + } + + ); + localStorage.setItem('pluginData', JSON.stringify(data)); + + // Checking the response status for success + if (updatePluginResponse.status === 204 || updatePluginResponse.status === 201) { + console.log("Plugin updated successfully."); + alert("Plugin updated successfully."); + getAllPlugins(newAccessToken,selectedrealm); + localStorage.setItem('pluginData', JSON.stringify(data)); + } else { + console.error(`Failed to update/add the plugin. Response: ${updatePluginResponse.statusText}`); + console.error("Error Details:", await updatePluginResponse.json()); + alert("Failed to update the plugin") + } + } else if (checkPluginResponse.status === 404) { + // If the status is 404, the plugin does not exist, so send a POST request + return fetch(`${serverUrl}/admin/realms/${selectedrealm}/identity-provider/instances`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${newAccessToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }) .then(response => { if (response.ok) { alert("Plugin added successfully."); - + localStorage.setItem('pluginData', JSON.stringify(data)); - + } else { console.error('Failed to add plugin:', response.status, response.statusText); alert("Failed to add plugin"); } }) .catch(error => { - + console.error('Network error or failed to send request:', error); }); - - - } else { - // If there is another status, an error occurred - - console.error(`Failed to retrieve the plugin. Response: ${checkPluginResponse.statusText}`); - alert("Failed to retrieve the plugin"); - throw new Error(`Failed to retrieve the plugin. Response: ${checkPluginResponse.statusText}`); - } - }) - - // Handling the response of the POST request (if executed) - .then(response => { - // ... (Additional code that was commented out) - }) - .catch(error => { - // ... (Additional code that was commented out) - }); - }else - {console.log('alias_input does not exist')} - + + + } else { + // If there is another status, an error occurred + + console.error(`Failed to retrieve the plugin. Response: ${checkPluginResponse.statusText}`); + alert("Failed to retrieve the plugin"); + throw new Error(`Failed to retrieve the plugin. Response: ${checkPluginResponse.statusText}`); + } + }) + + // Handling the response of the POST request (if executed) + .then(response => { + // ... (Additional code that was commented out) + }) + .catch(error => { + // ... (Additional code that was commented out) + }); + }else + {console.log('alias_input does not exist')} + // Setting a form element value to an empty string - + } else { console.log("Token is not updated"); } diff --git a/src/main/resources/saml-extended-frontend/js/Fielders.js b/src/main/resources/saml-extended-frontend/js/Fielders.js index 730be87..2796490 100644 --- a/src/main/resources/saml-extended-frontend/js/Fielders.js +++ b/src/main/resources/saml-extended-frontend/js/Fielders.js @@ -11,6 +11,7 @@ const Single_Sign_On_Service_URL_input = document.getElementById("ssoServiceUrl" const Single_Sign_On_Service_URL_inpu_edit = document.getElementById("ssoServiceUrl_edit"); const Single_Logout_Service_URL_input = document.getElementById("sloServiceUrl"); const allowedClockSkew_input = document.getElementById("allowedClockSkew"); +const assertionConsumingServiceIndex_input = document.getElementById("assertionConsumingServiceIndex"); const attributeConsumingServiceIndex_input = document.getElementById("attributeConsumingServiceIndex"); const attributeConsumingServiceName_input = document.getElementById("attributeConsumingServiceName"); const authnContextClassRefs_input = document.getElementById("authnContextClassRefs"); diff --git a/src/main/resources/saml-extended-frontend/js/InfoUpdaterAdd.js b/src/main/resources/saml-extended-frontend/js/InfoUpdaterAdd.js index a78d884..230f762 100644 --- a/src/main/resources/saml-extended-frontend/js/InfoUpdaterAdd.js +++ b/src/main/resources/saml-extended-frontend/js/InfoUpdaterAdd.js @@ -1,137 +1,135 @@ storedData = localStorage.getItem('pluginData'); +if (storedData) { if (storedData) { - if (storedData) { - - var pluginData = JSON.parse(storedData); - - function toggleCheckbox(configKey, checkbox) { - - if (pluginData.config && pluginData.config[configKey]) { - if (pluginData.config[configKey] == "true") { - checkbox.checked = true; - } else { - checkbox.checked = false; - - } - } - - } - function toggleCheckbox1(configKey1, checkbox1) { - - if (pluginData && pluginData[configKey1]) { - if (pluginData[configKey1] == true || pluginData[configKey1] == "true") { - checkbox1.checked = true; - } else { - checkbox1.checked = false; - - } - } - - } - - - toggleCheckbox('backchannelSupported', backchannel) - toggleCheckbox('allowCreate', allowCreate) - toggleCheckbox('postBindingResponse', httpPostBindingResponse) - toggleCheckbox('postBindingAuthnRequest', httpPostBindingAuthnRequest) - toggleCheckbox('postBindingLogout', httpPostBindingLogout) - toggleCheckbox('wantAssertionsSigned', wantAssertionsSigned) - toggleCheckbox('wantAssertionsEncrypted', wantAssertionsEncrypted) - toggleCheckbox('forceAuthn', forceAuthentication) - toggleCheckbox('signSpMetadata', signMetadata) - toggleCheckbox('loginHint', passSubject) - toggleCheckbox1('addReadTokenRoleOnCreate', storedTokensReadable) - toggleCheckbox1('storeToken', storeToken) - toggleCheckbox1('trustEmail', trustEmail) - toggleCheckbox1('linkOnly', accountLinkingOnly) - toggleCheckbox('hideOnLoginPage', hideLoginPage) - toggleCheckbox('includeArtifactResolutionServiceMetadata', ArtifactResolutionService_in_metadata) - toggleCheckbox('hideOnLoginPage', hideLoginPage) - toggleCheckbox('signArtifactResolutionRequest', Sign_Artifact_Resolution_Request) - toggleCheckbox('artifactResolutionHTTPArtifact', ArtifactResolution_via_HTTP_ARTIFACT) - toggleCheckbox('artifactResolutionSOAP', Artifact_Resolution_with_SOAP) - toggleCheckbox('artifactResolutionWithXmlHeader', Artifact_Resolution_with_XML_header) - toggleCheckbox('mutualTls', Mutual_TLS) - toggleCheckbox1('enabled', enabled) - toggleCheckbox('sendIdTokenOnLogout', id_token_hint) - toggleCheckbox('sendClientIdOnLogout', client_id_in_logout_requests) - if (pluginData.config && pluginData.config.wantAuthnRequestsSigned) { - - - if (pluginData.config.wantAuthnRequestsSigned == "true") { - SignatureAlgorithm.removeAttribute("disabled"); - SAMLSignatureKeyName.removeAttribute("disabled"); - encryption_algorithm.removeAttribute("disabled") - wantAuthnRequestsSigned.checked = true; + + var pluginData = JSON.parse(storedData); + + function toggleCheckbox(configKey, checkbox) { + + if (pluginData.config && pluginData.config[configKey]) { + if (pluginData.config[configKey] == "true") { + checkbox.checked = true; } else { - SignatureAlgorithm.setAttribute("disabled", "true"); - SAMLSignatureKeyName.setAttribute("disabled", "true"); - encryption_algorithm.setAttribute("disabled", "true"); - wantAuthnRequestsSigned.checked = false; - + checkbox.checked = false; + } } - - var additionalField1 = document.getElementById("ValidatingX509Certificates"); - if (pluginData.config && pluginData.config.validateSignature) { - validateSignatures_value = pluginData.config.validateSignature; - - if (pluginData.config.validateSignature === "true") { - additionalField1.removeAttribute("disabled"); - validateSignatures.checked = true; - - if (pluginData.config.signingCertificate) { - updateField('ValidatingX509Certificates', pluginData.config.signingCertificate); - } - if (pluginData.config.metadataDescriptorUrl) { - updateField('samlEntityDescriptor', pluginData.config.metadataDescriptorUrl); - } - - var samlEntityDescriptorElement = document.getElementById('saml_EntityDescriptor'); - if (samlEntityDescriptorElement) { - samlEntityDescriptorElement.style.display = 'block'; - } - - var useMetadataDescriptorUrlElement = document.getElementById('Use_Metadata_Descriptor_URL'); - if (useMetadataDescriptorUrlElement) { - useMetadataDescriptorUrlElement.style.display = 'block'; - } + + } + function toggleCheckbox1(configKey1, checkbox1) { + + if (pluginData && pluginData[configKey1]) { + if (pluginData[configKey1] == true || pluginData[configKey1] == "true") { + checkbox1.checked = true; } else { - validateSignatures.checked = false; - additionalField1.setAttribute("disabled", "true") - - var samlEntityDescriptorElement = document.getElementById('saml_EntityDescriptor'); - if (samlEntityDescriptorElement) { - samlEntityDescriptorElement.style.display = 'none'; - } - - var useMetadataDescriptorUrlElement = document.getElementById('Use_Metadata_Descriptor_URL'); - if (useMetadataDescriptorUrlElement) { - useMetadataDescriptorUrlElement.style.display = 'none'; - } + checkbox1.checked = false; + } - validateSignatures.dispatchEvent(new Event("change")); } - - - - - if (pluginData.config.attributeConsumingServiceMetadata) { - attributeServicesArray = JSON.parse(pluginData.config.attributeConsumingServiceMetadata); - renderAttributeServices(); + + } + + + toggleCheckbox('backchannelSupported', backchannel) + toggleCheckbox('allowCreate', allowCreate) + toggleCheckbox('postBindingResponse', httpPostBindingResponse) + toggleCheckbox('postBindingAuthnRequest', httpPostBindingAuthnRequest) + toggleCheckbox('postBindingLogout', httpPostBindingLogout) + toggleCheckbox('wantAssertionsSigned', wantAssertionsSigned) + toggleCheckbox('wantAssertionsEncrypted', wantAssertionsEncrypted) + toggleCheckbox('forceAuthn', forceAuthentication) + toggleCheckbox('signSpMetadata', signMetadata) + toggleCheckbox('loginHint', passSubject) + toggleCheckbox1('addReadTokenRoleOnCreate', storedTokensReadable) + toggleCheckbox1('storeToken', storeToken) + toggleCheckbox1('trustEmail', trustEmail) + toggleCheckbox1('linkOnly', accountLinkingOnly) + toggleCheckbox1('hideOnLogin', hideLoginPage) + toggleCheckbox('includeArtifactResolutionServiceMetadata', ArtifactResolutionService_in_metadata) + toggleCheckbox('signArtifactResolutionRequest', Sign_Artifact_Resolution_Request) + toggleCheckbox('artifactResolutionSOAP', Artifact_Resolution_with_SOAP) + toggleCheckbox('artifactResolutionWithXmlHeader', Artifact_Resolution_with_XML_header) + toggleCheckbox('mutualTls', Mutual_TLS) + toggleCheckbox1('enabled', enabled) + toggleCheckbox('sendIdTokenOnLogout', id_token_hint) + toggleCheckbox('sendClientIdOnLogout', client_id_in_logout_requests) + if (pluginData.config && pluginData.config.wantAuthnRequestsSigned) { + + + if (pluginData.config.wantAuthnRequestsSigned == "true") { + SignatureAlgorithm.removeAttribute("disabled"); + SAMLSignatureKeyName.removeAttribute("disabled"); + encryption_algorithm.removeAttribute("disabled") + wantAuthnRequestsSigned.checked = true; + } else { + SignatureAlgorithm.setAttribute("disabled", "true"); + SAMLSignatureKeyName.setAttribute("disabled", "true"); + encryption_algorithm.setAttribute("disabled", "true"); + wantAuthnRequestsSigned.checked = false; + } - - - function renderAttributeServices() { - var attributeServicesDiv = document.getElementById('attributeServices'); - attributeServicesDiv.innerHTML = ''; // Clear previous content - - attributeServicesArray.forEach(function(service, index) { - var newFieldsDiv = document.createElement('div'); - newFieldsDiv.classList.add('attribute-consuming-service'); // Add class 'attribute-consuming-service' - newFieldsDiv.dataset.index = index; // Set dataset index for form - - newFieldsDiv.innerHTML = ` + } + + var additionalField1 = document.getElementById("ValidatingX509Certificates"); + if (pluginData.config && pluginData.config.validateSignature) { + validateSignatures_value = pluginData.config.validateSignature; + + if (pluginData.config.validateSignature === "true") { + additionalField1.removeAttribute("disabled"); + validateSignatures.checked = true; + + if (pluginData.config.signingCertificate) { + updateField('ValidatingX509Certificates', pluginData.config.signingCertificate); + } + if (pluginData.config.metadataDescriptorUrl) { + updateField('samlEntityDescriptor', pluginData.config.metadataDescriptorUrl); + } + + var samlEntityDescriptorElement = document.getElementById('saml_EntityDescriptor'); + if (samlEntityDescriptorElement) { + samlEntityDescriptorElement.style.display = 'block'; + } + + var useMetadataDescriptorUrlElement = document.getElementById('Use_Metadata_Descriptor_URL'); + if (useMetadataDescriptorUrlElement) { + useMetadataDescriptorUrlElement.style.display = 'block'; + } + } else { + validateSignatures.checked = false; + additionalField1.setAttribute("disabled", "true") + + var samlEntityDescriptorElement = document.getElementById('saml_EntityDescriptor'); + if (samlEntityDescriptorElement) { + samlEntityDescriptorElement.style.display = 'none'; + } + + var useMetadataDescriptorUrlElement = document.getElementById('Use_Metadata_Descriptor_URL'); + if (useMetadataDescriptorUrlElement) { + useMetadataDescriptorUrlElement.style.display = 'none'; + } + } + validateSignatures.dispatchEvent(new Event("change")); + } + + + + + if (pluginData.config.attributeConsumingServiceMetadata) { + attributeServicesArray = JSON.parse(pluginData.config.attributeConsumingServiceMetadata); + renderAttributeServices(); + } + + + function renderAttributeServices() { + var attributeServicesDiv = document.getElementById('attributeServices'); + attributeServicesDiv.innerHTML = ''; // Clear previous content + + attributeServicesArray.forEach(function(service, index) { + var newFieldsDiv = document.createElement('div'); + newFieldsDiv.classList.add('attribute-consuming-service'); // Add class 'attribute-consuming-service' + newFieldsDiv.dataset.index = index; // Set dataset index for form + + newFieldsDiv.innerHTML = ` @@ -142,10 +140,10 @@ storedData = localStorage.getItem('pluginData'); `; - attributeServicesDiv.appendChild(newFieldsDiv); - }); - } - if(pluginData.config.attributeConsumingServiceMetadata) { + attributeServicesDiv.appendChild(newFieldsDiv); + }); + } + if(pluginData.config.attributeConsumingServiceMetadata) { attributeServicesArray = JSON.parse(pluginData.config.attributeConsumingServiceMetadata); fetch('/realms/master/samlconfig/pages/data', { method: 'POST', @@ -154,192 +152,193 @@ storedData = localStorage.getItem('pluginData'); }, body: JSON.stringify(attributeServicesArray) }) - .then(response => response.json()) - .then(data => { - }) - .catch(error => { - console.error('Error:', error); - });} - - var Validating_X509_Certificates=document.getElementById("Validating_X509_Certificates"); - - if (pluginData.config && pluginData.config.useMetadataDescriptorUrl) { - useMetadataDescriptorUrl_value = pluginData.config.useMetadataDescriptorUrl; - - if (pluginData.config.useMetadataDescriptorUrl == "true") { - document.getElementById("UseMetadataDescriptorURL").checked = true; - Validating_X509_Certificates.style.display='none' - document.getElementById("samlEntityDescriptor").setAttribute("required", "true"); - - } else { - document.getElementById("UseMetadataDescriptorURL").checked = false; - Validating_X509_Certificates.style.display='block' - document.getElementById("samlEntityDescriptor").removeAttribute("required"); - } - validateSignatures.dispatchEvent(new Event("change")); - } - - - - - if (pluginData.config && pluginData.config.artifactResolution) { - Artifact_Resolution_value = pluginData.config.artifactResolution; - if (pluginData.config.artifactResolution == "true") { - Artifact_Resolution.checked = true; - additionalField_endpoint.removeAttribute("disabled"); - } else { - Artifact_Resolution.checked = false; - additionalField_endpoint.setAttribute("disabled", "true"); - additionalField_endpoint.value = ''; - - - } - } - - } - - - function processAuthnContextArray(id, container) { - var element = document.getElementById(id); - if (pluginData.config && pluginData.config[id]) { - var myArray = JSON.parse(pluginData.config[id]); - updateField(id, myArray[0]); - for (var i = 1; i < myArray.length; i++) { - const newItem = document.createElement("div"); - newItem.className = "next-referral col-4"; - newItem.innerHTML = ''; - container.appendChild(newItem); - } - console.log(pluginData.config[id]); + .then(response => response.json()) + .then(data => { + }) + .catch(error => { + console.error('Error:', error); + });} + + var Validating_X509_Certificates=document.getElementById("Validating_X509_Certificates"); + + if (pluginData.config && pluginData.config.useMetadataDescriptorUrl) { + useMetadataDescriptorUrl_value = pluginData.config.useMetadataDescriptorUrl; + + if (pluginData.config.useMetadataDescriptorUrl == "true") { + document.getElementById("UseMetadataDescriptorURL").checked = true; + Validating_X509_Certificates.style.display='none' + document.getElementById("samlEntityDescriptor").setAttribute("required", "true"); + + } else { + document.getElementById("UseMetadataDescriptorURL").checked = false; + Validating_X509_Certificates.style.display='block' + document.getElementById("samlEntityDescriptor").removeAttribute("required"); } + validateSignatures.dispatchEvent(new Event("change")); } - - - - processAuthnContextArray("authnContextClassRefs", ClassRefs_items); - processAuthnContextArray("authnContextDeclRefs", DeclRefs_items); - - - if (pluginData.backchannelSupported) { - updateField('backchannel', pluginData.backchannelSupported); - } - - if (pluginData.displayName) { - updateField('displayName', pluginData.displayName); - } - if (pluginData.config.guiOrder) { - updateField('displayOrder', pluginData.config.guiOrder); - } - if (pluginData.config.entityId) { - updateField('spEntityId', pluginData.config.entityId) - } - - if (pluginData.config.idpEntityId) { - updateField('idpEntityId', pluginData.config.idpEntityId) - } - if (pluginData.config.singleSignOnServiceUrl) { - updateField('ssoServiceUrl', pluginData.config.singleSignOnServiceUrl); - } - if (pluginData.config.singleLogoutServiceUrl) { - updateField('sloServiceUrl', pluginData.config.singleLogoutServiceUrl); - } - - if (pluginData.config.nameIDPolicyFormat) { - const valueAfterFormat = extractValueAfterFormat(pluginData.config.nameIDPolicyFormat); - updateField('nameIdPolicy', valueAfterFormat); - } - if (pluginData.config.principalType) { - updateField('principalType', pluginData.config.principalType); - if (pluginData.config.principalType == "ATTRIBUTE" || pluginData.config.principalType == "FRIENDLY_ATTRIBUTE") { - if (pluginData.config.principalAttribute) { - updateField('principalAttribute', pluginData.config.principalAttribute); - - } - principalAttribute_input.removeAttribute("disabled"); + + + + + if (pluginData.config && pluginData.config.artifactResolution) { + Artifact_Resolution_value = pluginData.config.artifactResolution; + if (pluginData.config.artifactResolution == "true") { + Artifact_Resolution.checked = true; + additionalField_endpoint.removeAttribute("disabled"); } else { - principalAttribute_input.setAttribute("disabled", "true"); - principalAttribute_input.value = ''; - + Artifact_Resolution.checked = false; + additionalField_endpoint.setAttribute("disabled", "true"); + additionalField_endpoint.value = ''; + + } - }; - - - if (pluginData.config.encryptionAlgorithm) { - updateField('encryption_algorithm', pluginData.config.encryptionAlgorithm); } - - if (pluginData.config.signatureAlgorithm) { - updateField('SignatureAlgorithm', pluginData.config.signatureAlgorithm); - } - if (pluginData.config.xmlSigKeyInfoKeyNameTransformer) { - updateField('SAMLSignatureKeyName', pluginData.config.xmlSigKeyInfoKeyNameTransformer); - } - - if (pluginData.config.metadataValidUntilUnit) { - updateField('Metadata_expires_in', pluginData.config.metadataValidUntilUnit); - } - if (pluginData.config.metadataValidUntilPeriod) { - updateField('metadataValidUntilPeriod', pluginData.config.metadataValidUntilPeriod); - } - if (pluginData.config.linkedProviders) { - updateField('Linked_Providers', pluginData.config.linkedProviders); - } - if (pluginData.config.artifactResolutionEndpoint) { - updateField('Artifact_Resolution_Endpoint', pluginData.config.artifactResolutionEndpoint); - } - if (pluginData.config.charSet) { - updateField('CharacterSet', pluginData.config.charSet); - } - - if (pluginData.alias) { - updateField('alias', pluginData.alias); - - } - var selectedrealm = localStorage.getItem('selectedRealm'); - var ServerUrl1 = localStorage.getItem('ServerUrl') - var pluginalias=localStorage.setItem('pluginalias',`${pluginData.alias}`) - document.getElementById('redirectUri').value = `${ServerUrl1}/realms/${selectedrealm}/broker/${pluginData.alias}/endpoint` - - if (pluginData.config.allowedClockSkew) { - updateField('allowedClockSkew', pluginData.config.allowedClockSkew); - } - - if (pluginData.config.attributeConsumingServiceIndex) { - updateField('attributeConsumingServiceIndex', pluginData.config.attributeConsumingServiceIndex); - } - - if (pluginData.config.attributeConsumingServiceName) { - updateField('attributeConsumingServiceName', pluginData.config.attributeConsumingServiceName); - } - - if (pluginData.config.attributeConsumingServiceName) { - updateField('attributeConsumingServiceName', pluginData.config.attributeConsumingServiceName); - } - if (pluginData.config.authnContextComparisonType) { - updateField('comparison', pluginData.config.authnContextComparisonType); + + } + + + function processAuthnContextArray(id, container) { + var element = document.getElementById(id); + if (pluginData.config && pluginData.config[id]) { + var myArray = JSON.parse(pluginData.config[id]); + updateField(id, myArray[0]); + for (var i = 1; i < myArray.length; i++) { + const newItem = document.createElement("div"); + newItem.className = "next-referral col-4"; + newItem.innerHTML = ''; + container.appendChild(newItem); + } + console.log(pluginData.config[id]); } - - if (pluginData.config.syncMode) { - updateField('syncMode', pluginData.config.syncMode); + } + + + + processAuthnContextArray("authnContextClassRefs", ClassRefs_items); + processAuthnContextArray("authnContextDeclRefs", DeclRefs_items); + + + if (pluginData.backchannelSupported) { + updateField('backchannel', pluginData.backchannelSupported); + } + + if (pluginData.displayName) { + updateField('displayName', pluginData.displayName); + } + if (pluginData.config.guiOrder) { + updateField('displayOrder', pluginData.config.guiOrder); + } + if (pluginData.config.entityId) { + updateField('spEntityId', pluginData.config.entityId) + } + + if (pluginData.config.idpEntityId) { + updateField('idpEntityId', pluginData.config.idpEntityId) + } + if (pluginData.config.singleSignOnServiceUrl) { + updateField('ssoServiceUrl', pluginData.config.singleSignOnServiceUrl); + } + if (pluginData.config.singleLogoutServiceUrl) { + updateField('sloServiceUrl', pluginData.config.singleLogoutServiceUrl); + } + + if (pluginData.config.nameIDPolicyFormat) { + const valueAfterFormat = extractValueAfterFormat(pluginData.config.nameIDPolicyFormat); + updateField('nameIdPolicy', valueAfterFormat); + } + if (pluginData.config.principalType) { + updateField('principalType', pluginData.config.principalType); + if (pluginData.config.principalType == "ATTRIBUTE" || pluginData.config.principalType == "FRIENDLY_ATTRIBUTE") { + if (pluginData.config.principalAttribute) { + updateField('principalAttribute', pluginData.config.principalAttribute); + + } + principalAttribute_input.removeAttribute("disabled"); + } else { + principalAttribute_input.setAttribute("disabled", "true"); + principalAttribute_input.value = ''; + } - - - + }; + + + if (pluginData.config.encryptionAlgorithm) { + updateField('encryption_algorithm', pluginData.config.encryptionAlgorithm); + } + + if (pluginData.config.signatureAlgorithm) { + updateField('SignatureAlgorithm', pluginData.config.signatureAlgorithm); + } + if (pluginData.config.xmlSigKeyInfoKeyNameTransformer) { + updateField('SAMLSignatureKeyName', pluginData.config.xmlSigKeyInfoKeyNameTransformer); + } + + if (pluginData.config.metadataValidUntilUnit) { + updateField('Metadata_expires_in', pluginData.config.metadataValidUntilUnit); + } + if (pluginData.config.metadataValidUntilPeriod) { + updateField('metadataValidUntilPeriod', pluginData.config.metadataValidUntilPeriod); + } + if (pluginData.config.linkedProviders) { + updateField('Linked_Providers', pluginData.config.linkedProviders); + } + if (pluginData.config.artifactResolutionEndpoint) { + updateField('Artifact_Resolution_Endpoint', pluginData.config.artifactResolutionEndpoint); + } + if (pluginData.config.charSet) { + updateField('CharacterSet', pluginData.config.charSet); + } + + if (pluginData.alias) { + updateField('alias', pluginData.alias); + + } + var selectedrealm = localStorage.getItem('selectedRealm'); + var ServerUrl1 = localStorage.getItem('serverUrl') + var pluginalias=localStorage.setItem('pluginalias',`${pluginData.alias}`) + document.getElementById('redirectUri').value = `${ServerUrl1}/realms/${selectedrealm}/broker/${pluginData.alias}/endpoint` + + if (pluginData.config.allowedClockSkew) { + updateField('allowedClockSkew', pluginData.config.allowedClockSkew); + } + + if (pluginData.config.assertionConsumingServiceIndex) { + updateField('assertionConsumingServiceIndex', pluginData.config.assertionConsumingServiceIndex); + } + + if (pluginData.config.attributeConsumingServiceIndex) { + updateField('attributeConsumingServiceIndex', pluginData.config.attributeConsumingServiceIndex); + } + + if (pluginData.config.attributeConsumingServiceName) { + updateField('attributeConsumingServiceName', pluginData.config.attributeConsumingServiceName); + } + + if (pluginData.config.authnContextComparisonType) { + updateField('comparison', pluginData.config.authnContextComparisonType); + } + + if (pluginData.config.syncMode) { + updateField('syncMode', pluginData.config.syncMode); + } + + + } function toggleCheckbox(configKey, checkbox) { - + if (pluginData.config && pluginData.config[configKey]) { if (pluginData.config[configKey] == "true") { checkbox.checked = true; } else { checkbox.checked = false; - + } } - + } function extractValueAfterFormat(text) { diff --git a/src/main/resources/saml-extended-frontend/js/RestApiMethodes.js b/src/main/resources/saml-extended-frontend/js/RestApiMethodes.js index cd9fa3c..c607345 100644 --- a/src/main/resources/saml-extended-frontend/js/RestApiMethodes.js +++ b/src/main/resources/saml-extended-frontend/js/RestApiMethodes.js @@ -1,7 +1,7 @@ // export let selectedRealm; function getAllPlugins(accessToken, selectedRealm) { if (selectedRealm) { - fetch(`${ServerUrl}/admin/realms/${selectedRealm}/identity-provider/instances`, { + fetch(`${serverUrl}/admin/realms/${selectedRealm}/identity-provider/instances`, { method: 'GET', headers: { 'Authorization': ` Bearer ${accessToken}` @@ -58,7 +58,7 @@ window.handleAttributeServices=handleAttributeServices; function getAllRealms(accessToken) { keycloak.updateToken(300).then((bool) => { - fetch(`${ServerUrl}/admin/realms`, { + fetch(`${serverUrl}/admin/realms`, { method: 'GET', headers: { 'Authorization': `Bearer ${accessToken}` @@ -209,7 +209,7 @@ function handleDeleteButtonClick(plugin_alias, accessToken) { if (bool) { var selectedrealm = localStorage.getItem('selectedRealm'); // Assuming you have an API endpoint for deleting plugins - var deleteEndpoint = `${ServerUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${plugin_alias}`; + var deleteEndpoint = `${serverUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${plugin_alias}`; var accessToken = keycloak.token; // Send a DELETE request using Fetch API fetch(deleteEndpoint, { @@ -251,7 +251,7 @@ function getPluginDetails(alias, accessToken) { if (bool) { var accessToken = keycloak.token; var selectedrealm = localStorage.getItem('selectedRealm'); - fetch(`${ServerUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${alias}`, { + fetch(`${serverUrl}/admin/realms/${selectedrealm}/identity-provider/instances/${alias}`, { method: 'GET', headers: { 'Authorization': `Bearer ${accessToken}` diff --git a/src/main/resources/saml-extended-frontend/js/keycloakAdd.js b/src/main/resources/saml-extended-frontend/js/keycloakAdd.js index d511550..3c331d0 100644 --- a/src/main/resources/saml-extended-frontend/js/keycloakAdd.js +++ b/src/main/resources/saml-extended-frontend/js/keycloakAdd.js @@ -1,6 +1,6 @@ var accessToken; const keycloak =new Keycloak({ - url: `${ServerUrl}`, + url: `${serverUrl}`, realm: `${realm}`, clientId: `${clientid}`, redirectUri: `${redirectUri}`, @@ -9,7 +9,7 @@ const keycloak =new Keycloak({ }); document.getElementById('logout').addEventListener('click', () => { - window.location.href = `${ServerUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${postLogoutRedirect}&client_id=${clientid}`; + window.location.href = `${serverUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${postLogoutRedirect}&client_id=${clientid}`; }); keycloak @@ -23,7 +23,7 @@ keycloak const selectElement_postLoginFlow = document.getElementById('postLoginFlow'); const selectElement_firstLoginFlow = document.getElementById('firstLoginFlow'); - fetch(`${ServerUrl}/admin/realms/${selectedrealm}/ui-ext/authentication-management/flows`, { + fetch(`${serverUrl}/admin/realms/${selectedrealm}/ui-ext/authentication-management/flows`, { method: 'GET', headers: { 'Authorization': `Bearer ${accessToken}`, @@ -80,7 +80,7 @@ keycloak } else { alert("User does not have admin role. Access denied."); - window.location.href = `${ServerUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${post_logout_redirect_uri}&client_id=${clientid}`; + window.location.href = `${serverUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${post_logout_redirect_uri}&client_id=${clientid}`; } } diff --git a/src/main/resources/saml-extended-frontend/js/keycloakEdit.js b/src/main/resources/saml-extended-frontend/js/keycloakEdit.js index 0872946..49e966c 100644 --- a/src/main/resources/saml-extended-frontend/js/keycloakEdit.js +++ b/src/main/resources/saml-extended-frontend/js/keycloakEdit.js @@ -1,6 +1,6 @@ var accessToken; const keycloak = new Keycloak({ - url: `${ServerUrl}`, + url: `${serverUrl}`, realm: `${realm}`, clientId: `${clientid}`, redirectUri: `${redirectUri}`, @@ -9,7 +9,7 @@ const keycloak = new Keycloak({ }); document.getElementById('logout').addEventListener('click', () => { - window.location.href = `${ServerUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${postLogoutRedirect}&client_id=${clientid}`; + window.location.href = `${serverUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${postLogoutRedirect}&client_id=${clientid}`; }); keycloak @@ -24,7 +24,7 @@ keycloak const selectElement_firstLoginFlow = document.getElementById('firstLoginFlow'); var selectedrealm = localStorage.getItem('selectedRealm'); - fetch(`${ServerUrl}/admin/realms/${selectedrealm}/ui-ext/authentication-management/flows`, { + fetch(`${serverUrl}/admin/realms/${selectedrealm}/ui-ext/authentication-management/flows`, { method: 'GET', headers: { 'Authorization': `Bearer ${accessToken}`, @@ -91,7 +91,7 @@ keycloak } else { alert("User does not have admin role. Access denied."); - window.location.href = `${ServerUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${post_logout_redirect_uri}&client_id=${clientid}`; + window.location.href = `${serverUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${post_logout_redirect_uri}&client_id=${clientid}`; } diff --git a/src/main/resources/saml-extended-frontend/js/keycloakList.js b/src/main/resources/saml-extended-frontend/js/keycloakList.js index 9433f86..21db915 100644 --- a/src/main/resources/saml-extended-frontend/js/keycloakList.js +++ b/src/main/resources/saml-extended-frontend/js/keycloakList.js @@ -1,6 +1,6 @@ var accessToken; const keycloak = new Keycloak({ - url: `${ServerUrl}`, + url: `${serverUrl}`, realm: `${realm}`, clientId: `${clientid}`, redirectUri: `${redirectUri}`, @@ -10,7 +10,7 @@ const keycloak = new Keycloak({ document.getElementById('logout').addEventListener('click', () => { - window.location.href = `${ServerUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${postLogoutRedirect}&client_id=${clientid}`; + window.location.href = `${serverUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${postLogoutRedirect}&client_id=${clientid}`; }); keycloak @@ -29,7 +29,7 @@ keycloak document.body.style.display = 'block'; } else { alert("User does not have admin role. Access denied."); - window.location.href = `${ServerUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${post_logout_redirect_uri}&client_id=${clientid}`; + window.location.href = `${serverUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${post_logout_redirect_uri}&client_id=${clientid}`; } } else { alert("User authentication failed!"); diff --git a/src/main/resources/saml-extended-frontend/pages/addprovider.html b/src/main/resources/saml-extended-frontend/pages/addprovider.html index c417d61..47c1ebb 100644 --- a/src/main/resources/saml-extended-frontend/pages/addprovider.html +++ b/src/main/resources/saml-extended-frontend/pages/addprovider.html @@ -356,8 +356,8 @@

Saml-extended

@@ -378,9 +378,9 @@
Redirect URI value="http://localhost:8080/realms/master/broker/saml-extended/endpoint" id="redirectUri" readonly>
Alias * question markAlias *
Display Name question markEndpoints SAML 2.0 Service Provider Metadata + var selectedRealm = localStorage.getItem('selectedRealm'); + var serverUrl = localStorage.getItem('serverUrl'); + var alias_for_endpoint = localStorage.getItem('alias_for_endpoint'); + document.getElementById('metadataLink').onclick = function(event) { + event.preventDefault(); + window.open(`${serverUrl}/realms/${selectedRealm}/broker/${alias_for_endpoint}/endpoint/descriptor`, '_blank');}

SAML settings

Service Provider Entity ID @@ -563,19 +563,22 @@
HTTP-POST Binding Response onclick="alert('Indicates whether to respond to requests using HTTP-POST binding. If false, HTTP-REDIRECT binding will be used.')">
- +
ARTIFACT binding response
+
HTTP-POST Binding for AuthnRequest question mark
-
@@ -874,7 +882,7 @@
Metadata expires in
- +
@@ -947,15 +955,6 @@
Sign Artifact Resolution Request -
ArtifactResolution via HTTP-ARTIFACT - question mark -
-
Artifact Resolution with SOAP question mark @@ -1001,14 +1000,14 @@

Attribute Consuming Service

@@ -1062,11 +1061,11 @@

Attribute Consuming Service

diff --git a/src/main/resources/saml-extended-frontend/pages/editprovider.html b/src/main/resources/saml-extended-frontend/pages/editprovider.html index 08c7bb1..1b59d0d 100644 --- a/src/main/resources/saml-extended-frontend/pages/editprovider.html +++ b/src/main/resources/saml-extended-frontend/pages/editprovider.html @@ -339,9 +339,9 @@

Saml-extended

@@ -360,35 +360,35 @@

General Settings

Redirect URI question mark + onclick="alert('The redirect uri to use when configuring the identity provider.')">
+ value="http://localhost:8080/realms/master/broker/saml-extended/endpoint" id="redirectUri" readonly>
Alias * question mark + onclick="alert('The alias uniquely identifies an identity provider and it is also used to build the redirect uri.')">
-
Display Name - question mark -
- +
Display Name + question mark +
+
Display Order question mark + onclick="alert('Number defining the order of the providers in GUI (for example, on the Login page). The lowest number will be applied first.')">
Endpoints question mark + onclick="alert('The alias uniquely identifies an identity provider and it is also used to build the redirect uri.')">
@@ -397,48 +397,48 @@
Endpoints

SAML settings

Service Provider Entity ID question mark + onclick="alert('The Entity ID that will be used to uniquely identify this SAML Service Provider.')">
Identity Provider Entity ID question mark + onclick="alert('The Entity ID used to validate the Issuer for received SAML assertions. If empty, no Issuer validation is performed.')">
Single Sign-On Service URL * question mark + onclick="alert('The Url that must be used to send authentication requests (SAML AuthnRequest).')">
Single Logout Service URL question mark + onclick="alert('The Url that must be used to send logout requests.')">
Backchannel Logout question mark + onclick="alert('Does the external IDP support backchannel logout?')">
@@ -730,10 +742,10 @@
AuthnContext ClassRefs
AuthnContext DeclRefs question mark
+ alt="question mark" onclick="alert('Ordered list of requested AuthnContext DeclRefs.')">
+ class="form-control input-md">
@@ -746,7 +758,7 @@

Advanced Settings

Store Tokens question mark + onclick="alert('Enable/disable if tokens must be stored after authenticating users')">