@Override
  public void handleMessage(SoapMessage msg) throws Fault {
    Endpoint ep = msg.getExchange().get(Endpoint.class);
    sdc.set(ep.getSecurityDomainContext());
    try {
      SecurityToken token = msg.get(SecurityToken.class);
      SecurityContext context = msg.get(SecurityContext.class);
      if (token == null || context == null || context.getUserPrincipal() == null) {
        super.handleMessage(msg);
        return;
      }
      UsernameToken ut = (UsernameToken) token;

      Subject subject =
          createSubject(
              ut.getName(), ut.getPassword(), ut.isHashed(), ut.getNonce(), ut.getCreatedTime());

      SecurityContext sc = doCreateSecurityContext(context.getUserPrincipal(), subject);
      msg.put(SecurityContext.class, sc);
    } finally {
      if (sdc != null) {
        sdc.remove();
      }
    }
  }
  public Response handleRequest(Message message, ClassResourceInfo resourceClass) {
    try {
      SecurityContext securityContext = message.get(SecurityContext.class);
      Method method = getTargetMethod(message);
      if (!authorize(securityContext, method)) {
        log.warn(
            "User :"******"trying to perform unauthrorized action"
                + " against the resource :"
                + method);
        return Response.status(Response.Status.FORBIDDEN)
            .type(MediaType.APPLICATION_JSON)
            .entity(
                Utils.buildMessage(
                    "The user does not have required permissions to " + "perform this operation"))
            .build();
      }
      return null;

    } catch (Exception exception) {
      log.error("Unexpercted error occured while REST api, authorization process", exception);
      return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
          .type(MediaType.APPLICATION_JSON)
          .entity(Utils.buildMessage("Unexpected error. Please contact the system admin"))
          .build();
    }
  }
  protected void processToken(SoapMessage message) {
    Header h = findSecurityHeader(message, false);
    if (h == null) {
      return;
    }
    boolean utWithCallbacks =
        MessageUtils.getContextualBoolean(message, SecurityConstants.VALIDATE_TOKEN, true);

    Element el = (Element) h.getObject();
    Element child = DOMUtils.getFirstElement(el);
    while (child != null) {
      if (SPConstants.USERNAME_TOKEN.equals(child.getLocalName())
          && WSConstants.WSSE_NS.equals(child.getNamespaceURI())) {
        try {
          Principal principal = null;
          Subject subject = null;
          if (utWithCallbacks) {
            final WSSecurityEngineResult result = validateToken(child, message);
            principal = (Principal) result.get(WSSecurityEngineResult.TAG_PRINCIPAL);
            subject = (Subject) result.get(WSSecurityEngineResult.TAG_SUBJECT);
          } else {
            boolean bspCompliant = isWsiBSPCompliant(message);
            principal = parseTokenAndCreatePrincipal(child, bspCompliant);
            WSS4JTokenConverter.convertToken(message, principal);
          }

          SecurityContext sc = message.get(SecurityContext.class);
          if (sc == null || sc.getUserPrincipal() == null) {
            if (subject != null && principal != null) {
              message.put(SecurityContext.class, createSecurityContext(principal, subject));
            } else if (principal instanceof UsernameTokenPrincipal) {
              UsernameTokenPrincipal utPrincipal = (UsernameTokenPrincipal) principal;
              String nonce = null;
              if (utPrincipal.getNonce() != null) {
                nonce = Base64.encode(utPrincipal.getNonce());
              }
              subject =
                  createSubject(
                      utPrincipal.getName(),
                      utPrincipal.getPassword(),
                      utPrincipal.isPasswordDigest(),
                      nonce,
                      utPrincipal.getCreatedTime());
              message.put(SecurityContext.class, createSecurityContext(utPrincipal, subject));
            }
          }

          if (principal instanceof UsernameTokenPrincipal) {
            storeResults((UsernameTokenPrincipal) principal, message);
          }
        } catch (WSSecurityException ex) {
          throw new Fault(ex);
        } catch (Base64DecodingException ex) {
          throw new Fault(ex);
        }
      }
      child = DOMUtils.getNextElement(child);
    }
  }
  public void handleMessage(Message message) throws Fault {
    SecurityContext context = message.get(SecurityContext.class);
    if (context == null) {
      return;
    }
    Principal principal = context.getUserPrincipal();
    UsernameToken usernameToken = (UsernameToken) message.get(SecurityToken.class);
    if (principal == null
        || usernameToken == null
        || !principal.getName().equals(usernameToken.getName())) {
      return;
    }

    // Read the user from Syncope and get the roles
    WebClient client =
        WebClient.create(address, Collections.singletonList(new JacksonJsonProvider()));

    String authorizationHeader =
        "Basic "
            + Base64Utility.encode(
                (usernameToken.getName() + ":" + usernameToken.getPassword()).getBytes());

    client.header("Authorization", authorizationHeader);

    client = client.path("users/self");
    UserTO user = null;
    try {
      user = client.get(UserTO.class);
      if (user == null) {
        Exception exception = new Exception("Authentication failed");
        throw new Fault(exception);
      }
    } catch (RuntimeException ex) {
      if (log.isDebugEnabled()) {
        log.debug(ex.getMessage(), ex);
      }
      throw new Fault(ex);
    }

    // Now get the roles
    List<MembershipTO> membershipList = user.getMemberships();
    Subject subject = new Subject();
    subject.getPrincipals().add(principal);
    for (MembershipTO membership : membershipList) {
      String roleName = membership.getRoleName();
      subject.getPrincipals().add(new SimpleGroup(roleName, usernameToken.getName()));
    }
    subject.setReadOnly();

    message.put(SecurityContext.class, new DefaultSecurityContext(principal, subject));
  }
  @Test
  public void testEncryptedUsernameToken() throws Exception {
    Map<String, String> outProperties = new HashMap<String, String>();
    outProperties.put(
        WSHandlerConstants.ACTION,
        WSHandlerConstants.USERNAME_TOKEN + " " + WSHandlerConstants.ENCRYPT);
    outProperties.put(WSHandlerConstants.ENC_PROP_FILE, "outsecurity.properties");
    outProperties.put(WSHandlerConstants.USER, "alice");
    outProperties.put("password", "alicePassword");
    outProperties.put(WSHandlerConstants.ENCRYPTION_USER, "myalias");
    outProperties.put(
        WSHandlerConstants.ENCRYPTION_PARTS, "{Content}{" + WSConstants.WSSE_NS + "}UsernameToken");

    Map<String, String> inProperties = new HashMap<String, String>();
    inProperties.put(
        WSHandlerConstants.ACTION,
        WSHandlerConstants.USERNAME_TOKEN + " " + WSHandlerConstants.ENCRYPT);
    inProperties.put(WSHandlerConstants.DEC_PROP_FILE, "insecurity.properties");
    inProperties.put(
        WSHandlerConstants.PW_CALLBACK_CLASS, "org.apache.cxf.ws.security.wss4j.TestPwdCallback");

    List<String> xpaths = new ArrayList<String>();
    xpaths.add("//wsse:Security");

    SoapMessage inmsg = makeInvocation(outProperties, xpaths, inProperties);
    List<WSHandlerResult> handlerResults = getResults(inmsg);

    assertNotNull(handlerResults);
    assertSame(handlerResults.size(), 1);

    //
    // This should contain exactly 2 protection results
    //
    final java.util.List<WSSecurityEngineResult> protectionResults =
        handlerResults.get(0).getResults();
    assertNotNull(protectionResults);
    assertSame(protectionResults.size(), 2);

    final Principal p1 =
        (Principal) protectionResults.get(0).get(WSSecurityEngineResult.TAG_PRINCIPAL);
    final Principal p2 =
        (Principal) protectionResults.get(1).get(WSSecurityEngineResult.TAG_PRINCIPAL);
    assertTrue(p1 instanceof UsernameTokenPrincipal || p2 instanceof UsernameTokenPrincipal);

    Principal utPrincipal = p1 instanceof UsernameTokenPrincipal ? p1 : p2;

    SecurityContext securityContext = inmsg.get(SecurityContext.class);
    assertNotNull(securityContext);
    assertSame(securityContext.getUserPrincipal(), utPrincipal);
  }
  private boolean authorize(SecurityContext securityContext, Method targetMethod) throws Exception {
    // first we try to see whether this is a super.tenant only operation
    String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
    int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
    if (superTenantServiceSet.contains(targetMethod.getName())
        && !isCurrentUserSuperTenant(tenantDomain, tenantId)) {
      return false;
    }
    // authorize using permissionString given as annotation in the service class
    String userName = securityContext.getUserPrincipal().getName();
    String permissionString = authorizationActionMap.get(targetMethod.getName());

    // get the authorization manager for this tenant..
    UserRealm userRealm = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm();
    AuthorizationManager authorizationManager = userRealm.getAuthorizationManager();

    boolean isAuthorized =
        isAuthorized(authorizationManager, userName, permissionString, ACTION_ON_RESOURCE);
    return isAuthorized;
  }
  /** This method is called by {@link CxfConsumer}. */
  public void populateExchangeFromCxfRequest(
      org.apache.cxf.message.Exchange cxfExchange, Exchange camelExchange) {

    Method method = null;
    QName operationName = null;
    ExchangePattern mep = ExchangePattern.InOut;

    // extract binding operation information
    BindingOperationInfo boi =
        camelExchange.getProperty(BindingOperationInfo.class.getName(), BindingOperationInfo.class);
    if (boi != null) {
      Service service = cxfExchange.get(Service.class);
      if (service != null) {
        MethodDispatcher md = (MethodDispatcher) service.get(MethodDispatcher.class.getName());
        if (md != null) {
          method = md.getMethod(boi);
        }
      }

      if (boi.getOperationInfo().isOneWay()) {
        mep = ExchangePattern.InOnly;
      }

      operationName = boi.getName();
    }

    // set operation name in header
    if (operationName != null) {
      camelExchange
          .getIn()
          .setHeader(CxfConstants.OPERATION_NAMESPACE, boi.getName().getNamespaceURI());
      camelExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, boi.getName().getLocalPart());
      if (LOG.isTraceEnabled()) {
        LOG.trace(
            "Set IN header: {}={}",
            CxfConstants.OPERATION_NAMESPACE,
            boi.getName().getNamespaceURI());
        LOG.trace(
            "Set IN header: {}={}", CxfConstants.OPERATION_NAME, boi.getName().getLocalPart());
      }
    } else if (method != null) {
      camelExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, method.getName());
      if (LOG.isTraceEnabled()) {
        LOG.trace("Set IN header: {}={}", CxfConstants.OPERATION_NAME, method.getName());
      }
    }

    // set message exchange pattern
    camelExchange.setPattern(mep);
    LOG.trace("Set exchange MEP: {}", mep);

    // propagate headers
    Message cxfMessage = cxfExchange.getInMessage();
    propagateHeadersFromCxfToCamel(cxfMessage, camelExchange.getIn(), camelExchange);

    // propagate the security subject from CXF security context
    SecurityContext securityContext = cxfMessage.get(SecurityContext.class);
    if (securityContext instanceof LoginSecurityContext
        && ((LoginSecurityContext) securityContext).getSubject() != null) {
      camelExchange
          .getIn()
          .getHeaders()
          .put(Exchange.AUTHENTICATION, ((LoginSecurityContext) securityContext).getSubject());
    } else if (securityContext != null && securityContext.getUserPrincipal() != null) {
      Subject subject = new Subject();
      subject.getPrincipals().add(securityContext.getUserPrincipal());
      camelExchange.getIn().getHeaders().put(Exchange.AUTHENTICATION, subject);
    }

    // Propagating properties from CXF Exchange to Camel Exchange has an
    // side effect of copying reply side stuff when the producer is retried.
    // So, we do not want to do this.
    // camelExchange.getProperties().putAll(cxfExchange);

    // propagate request context
    Object value = cxfMessage.get(Client.REQUEST_CONTEXT);
    if (value != null
        && !headerFilterStrategy.applyFilterToExternalHeaders(
            Client.REQUEST_CONTEXT, value, camelExchange)) {
      camelExchange.getIn().setHeader(Client.REQUEST_CONTEXT, value);
      LOG.trace("Populate context from CXF message {} value={}", Client.REQUEST_CONTEXT, value);
    }

    // setup the charset from content-type header
    setCharsetWithContentType(camelExchange);

    // set body
    Object body =
        DefaultCxfBinding.getContentFromCxf(
            cxfMessage,
            camelExchange.getProperty(CxfConstants.DATA_FORMAT_PROPERTY, DataFormat.class));
    if (body != null) {
      camelExchange.getIn().setBody(body);
    }

    // propagate attachments if the data format is not POJO
    if (cxfMessage.getAttachments() != null
        && !camelExchange
            .getProperty(CxfConstants.DATA_FORMAT_PROPERTY, DataFormat.class)
            .equals(DataFormat.POJO)) {
      for (Attachment attachment : cxfMessage.getAttachments()) {
        camelExchange.getIn().addAttachment(attachment.getId(), attachment.getDataHandler());
      }
    }
  }