Example #1
0
 private JaxrsSAML2BindingBuilder createBindingBuilder(SamlClient samlClient) {
   JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder();
   if (samlClient.requiresRealmSignature()) {
     KeyManager.ActiveKey keys = session.keys().getActiveKey(realm);
     binding
         .signatureAlgorithm(samlClient.getSignatureAlgorithm())
         .signWith(keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate())
         .signDocument();
   }
   return binding;
 }
Example #2
0
    protected Response logoutRequest(
        LogoutRequestType logoutRequest, ClientModel client, String relayState) {
      SamlClient samlClient = new SamlClient(client);
      // validate destination
      if (logoutRequest.getDestination() != null
          && !uriInfo.getAbsolutePath().equals(logoutRequest.getDestination())) {
        event.detail(Details.REASON, "invalid_destination");
        event.error(Errors.INVALID_SAML_LOGOUT_REQUEST);
        return ErrorPage.error(session, Messages.INVALID_REQUEST);
      }

      // authenticate identity cookie, but ignore an access token timeout as we're logging out
      // anyways.
      AuthenticationManager.AuthResult authResult =
          authManager.authenticateIdentityCookie(session, realm, false);
      if (authResult != null) {
        String logoutBinding = getBindingType();
        if ("true".equals(samlClient.forcePostBinding()))
          logoutBinding = SamlProtocol.SAML_POST_BINDING;
        String bindingUri = SamlProtocol.getLogoutServiceUrl(uriInfo, client, logoutBinding);
        UserSessionModel userSession = authResult.getSession();
        userSession.setNote(SamlProtocol.SAML_LOGOUT_BINDING_URI, bindingUri);
        if (samlClient.requiresRealmSignature()) {
          userSession.setNote(
              SamlProtocol.SAML_LOGOUT_SIGNATURE_ALGORITHM,
              samlClient.getSignatureAlgorithm().toString());
        }
        if (relayState != null)
          userSession.setNote(SamlProtocol.SAML_LOGOUT_RELAY_STATE, relayState);
        userSession.setNote(SamlProtocol.SAML_LOGOUT_REQUEST_ID, logoutRequest.getID());
        userSession.setNote(SamlProtocol.SAML_LOGOUT_BINDING, logoutBinding);
        userSession.setNote(
            SamlProtocol.SAML_LOGOUT_CANONICALIZATION, samlClient.getCanonicalizationMethod());
        userSession.setNote(
            AuthenticationManager.KEYCLOAK_LOGOUT_PROTOCOL, SamlProtocol.LOGIN_PROTOCOL);
        // remove client from logout requests
        for (ClientSessionModel clientSession : userSession.getClientSessions()) {
          if (clientSession.getClient().getId().equals(client.getId())) {
            clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
          }
        }
        logger.debug("browser Logout");
        return authManager.browserLogout(
            session, realm, userSession, uriInfo, clientConnection, headers);
      } else if (logoutRequest.getSessionIndex() != null) {
        for (String sessionIndex : logoutRequest.getSessionIndex()) {
          ClientSessionModel clientSession =
              session.sessions().getClientSession(realm, sessionIndex);
          if (clientSession == null) continue;
          UserSessionModel userSession = clientSession.getUserSession();
          if (clientSession.getClient().getClientId().equals(client.getClientId())) {
            // remove requesting client from logout
            clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());

            // Remove also other clientSessions of this client as there could be more in this
            // UserSession
            if (userSession != null) {
              for (ClientSessionModel clientSession2 : userSession.getClientSessions()) {
                if (clientSession2.getClient().getId().equals(client.getId())) {
                  clientSession2.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
                }
              }
            }
          }

          try {
            authManager.backchannelLogout(
                session, realm, userSession, uriInfo, clientConnection, headers, true);
          } catch (Exception e) {
            logger.warn("Failure with backchannel logout", e);
          }
        }
      }

      // default

      String logoutBinding = getBindingType();
      String logoutBindingUri = SamlProtocol.getLogoutServiceUrl(uriInfo, client, logoutBinding);
      String logoutRelayState = relayState;
      SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
      builder.logoutRequestID(logoutRequest.getID());
      builder.destination(logoutBindingUri);
      builder.issuer(RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString());
      JaxrsSAML2BindingBuilder binding =
          new JaxrsSAML2BindingBuilder().relayState(logoutRelayState);
      if (samlClient.requiresRealmSignature()) {
        SignatureAlgorithm algorithm = samlClient.getSignatureAlgorithm();
        KeyManager.ActiveKey keys = session.keys().getActiveKey(realm);
        binding
            .signatureAlgorithm(algorithm)
            .signWith(keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate())
            .signDocument();
      }
      try {
        if (SamlProtocol.SAML_POST_BINDING.equals(logoutBinding)) {
          return binding.postBinding(builder.buildDocument()).response(logoutBindingUri);
        } else {
          return binding.redirectBinding(builder.buildDocument()).response(logoutBindingUri);
        }
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
Example #3
0
  @Override
  public Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode) {
    ClientSessionModel clientSession = accessCode.getClientSession();
    ClientModel client = clientSession.getClient();
    SamlClient samlClient = new SamlClient(client);
    String requestID = clientSession.getNote(SAML_REQUEST_ID);
    String relayState = clientSession.getNote(GeneralConstants.RELAY_STATE);
    String redirectUri = clientSession.getRedirectUri();
    String responseIssuer = getResponseIssuer(realm);
    String nameIdFormat = getNameIdFormat(samlClient, clientSession);
    String nameId = getNameId(nameIdFormat, clientSession, userSession);

    // save NAME_ID and format in clientSession as they may be persistent or transient or email and
    // not username
    // we'll need to send this back on a logout
    clientSession.setNote(SAML_NAME_ID, nameId);
    clientSession.setNote(SAML_NAME_ID_FORMAT, nameIdFormat);

    SAML2LoginResponseBuilder builder = new SAML2LoginResponseBuilder();
    builder
        .requestID(requestID)
        .destination(redirectUri)
        .issuer(responseIssuer)
        .assertionExpiration(realm.getAccessCodeLifespan())
        .subjectExpiration(realm.getAccessTokenLifespan())
        .sessionIndex(clientSession.getId())
        .requestIssuer(clientSession.getClient().getClientId())
        .nameIdentifier(nameIdFormat, nameId)
        .authMethod(JBossSAMLURIConstants.AC_UNSPECIFIED.get());
    if (!samlClient.includeAuthnStatement()) {
      builder.disableAuthnStatement(true);
    }

    List<ProtocolMapperProcessor<SAMLAttributeStatementMapper>> attributeStatementMappers =
        new LinkedList<>();
    List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> loginResponseMappers =
        new LinkedList<>();
    ProtocolMapperProcessor<SAMLRoleListMapper> roleListMapper = null;

    Set<ProtocolMapperModel> mappings = accessCode.getRequestedProtocolMappers();
    for (ProtocolMapperModel mapping : mappings) {

      ProtocolMapper mapper =
          (ProtocolMapper)
              session
                  .getKeycloakSessionFactory()
                  .getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
      if (mapper == null) continue;
      if (mapper instanceof SAMLAttributeStatementMapper) {
        attributeStatementMappers.add(
            new ProtocolMapperProcessor<SAMLAttributeStatementMapper>(
                (SAMLAttributeStatementMapper) mapper, mapping));
      }
      if (mapper instanceof SAMLLoginResponseMapper) {
        loginResponseMappers.add(
            new ProtocolMapperProcessor<SAMLLoginResponseMapper>(
                (SAMLLoginResponseMapper) mapper, mapping));
      }
      if (mapper instanceof SAMLRoleListMapper) {
        roleListMapper =
            new ProtocolMapperProcessor<SAMLRoleListMapper>((SAMLRoleListMapper) mapper, mapping);
      }
    }

    Document samlDocument = null;
    try {
      ResponseType samlModel = builder.buildModel();
      final AttributeStatementType attributeStatement =
          populateAttributeStatements(
              attributeStatementMappers, session, userSession, clientSession);
      populateRoles(roleListMapper, session, userSession, clientSession, attributeStatement);

      // SAML Spec 2.7.3 AttributeStatement must contain one or more Attribute or EncryptedAttribute
      if (attributeStatement.getAttributes().size() > 0) {
        AssertionType assertion = samlModel.getAssertions().get(0).getAssertion();
        assertion.addStatement(attributeStatement);
      }

      samlModel =
          transformLoginResponse(
              loginResponseMappers, samlModel, session, userSession, clientSession);
      samlDocument = builder.buildDocument(samlModel);
    } catch (Exception e) {
      logger.error("failed", e);
      return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
    }

    JaxrsSAML2BindingBuilder bindingBuilder = new JaxrsSAML2BindingBuilder();
    bindingBuilder.relayState(relayState);

    KeyManager keyManager = session.keys();
    KeyManager.ActiveKey keys = keyManager.getActiveKey(realm);

    if (samlClient.requiresRealmSignature()) {
      String canonicalization = samlClient.getCanonicalizationMethod();
      if (canonicalization != null) {
        bindingBuilder.canonicalizationMethod(canonicalization);
      }
      bindingBuilder
          .signatureAlgorithm(samlClient.getSignatureAlgorithm())
          .signWith(keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate())
          .signDocument();
    }
    if (samlClient.requiresAssertionSignature()) {
      String canonicalization = samlClient.getCanonicalizationMethod();
      if (canonicalization != null) {
        bindingBuilder.canonicalizationMethod(canonicalization);
      }
      bindingBuilder
          .signatureAlgorithm(samlClient.getSignatureAlgorithm())
          .signWith(keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate())
          .signAssertions();
    }
    if (samlClient.requiresEncryption()) {
      PublicKey publicKey = null;
      try {
        publicKey = SamlProtocolUtils.getEncryptionValidationKey(client);
      } catch (Exception e) {
        logger.error("failed", e);
        return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
      }
      bindingBuilder.encrypt(publicKey);
    }
    try {
      return buildAuthenticatedResponse(clientSession, redirectUri, samlDocument, bindingBuilder);
    } catch (Exception e) {
      logger.error("failed", e);
      return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
    }
  }