private boolean readTokenCacheItems(String authority) throws JSONException {

    final AuthenticationContext authContext;
    try {
      authContext = getOrCreateContext(authority);
    } catch (Exception e) {
      callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, e.getMessage()));
      return true;
    }

    JSONArray result = new JSONArray();
    ITokenCacheStore cache = authContext.getCache();

    if (cache instanceof ITokenStoreQuery) {
      Iterator<TokenCacheItem> cacheItems = ((ITokenStoreQuery) cache).getAll();

      while (cacheItems.hasNext()) {
        TokenCacheItem item = cacheItems.next();
        result.put(tokenItemToJSON(item));
      }
    }

    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));

    return true;
  }
  public @Nonnull List<String> get(@Nullable String bucket)
      throws CloudException, InternalException {
    AuthenticationContext context = provider.getAuthenticationContext();
    String endpoint = context.getStorageUrl();

    if (endpoint == null) {
      throw new CloudException("No storage endpoint exists for " + context.getMyRegion());
    }
    String response =
        getString(context.getAuthToken(), endpoint, bucket == null ? "/" : "/" + bucket);
    ArrayList<String> entries = new ArrayList<String>();

    if (response != null) {
      response = response.trim();
      if (response.length() > 0) {
        String[] lines = response.split("\n");

        if (lines.length < 1) {
          entries.add(response);
        } else {
          for (String line : lines) {
            entries.add(line.trim());
          }
        }
      }
    }
    return entries;
  }
  public void delete(@Nonnull String bucket) throws CloudException, InternalException {
    AuthenticationContext context = provider.getAuthenticationContext();
    String endpoint = context.getStorageUrl();

    if (endpoint == null) {
      throw new CloudException("No storage endpoint exists for " + context.getMyRegion());
    }
    delete(context.getAuthToken(), endpoint, "/" + bucket);
  }
  public @Nullable InputStream get(@Nonnull String bucket, @Nonnull String object)
      throws CloudException, InternalException {
    AuthenticationContext context = provider.getAuthenticationContext();
    String endpoint = context.getStorageUrl();

    if (endpoint == null) {
      throw new CloudException("No storage endpoint exists for " + context.getMyRegion());
    }
    return getStream(context.getAuthToken(), endpoint, "/" + bucket + "/" + object);
  }
  @SuppressWarnings("unused")
  public @Nullable Map<String, String> head(@Nonnull String bucket)
      throws CloudException, InternalException {
    AuthenticationContext context = provider.getAuthenticationContext();
    String endpoint = context.getStorageUrl();

    if (endpoint == null) {
      throw new CloudException("No storage endpoint exists for " + context.getMyRegion());
    }
    return head(context.getAuthToken(), endpoint, "/" + bucket);
  }
  private boolean clearTokenCache(String authority) {
    final AuthenticationContext authContext;
    try {
      authContext = getOrCreateContext(authority);
    } catch (Exception e) {
      callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, e.getMessage()));
      return true;
    }

    authContext.getCache().removeAll();
    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
    return true;
  }
  public void put(
      @Nonnull String bucket,
      @Nonnull String object,
      @Nullable String md5Hash,
      @Nonnull InputStream payload)
      throws CloudException, InternalException {
    AuthenticationContext context = provider.getAuthenticationContext();
    String endpoint = context.getStorageUrl();

    if (endpoint == null) {
      throw new CloudException("No storage endpoint exists for " + context.getMyRegion());
    }
    putStream(context.getAuthToken(), endpoint, "/" + bucket + "/" + object, md5Hash, payload);
  }
  private boolean acquireTokenSilentAsync(
      String authority, String resourceUrl, String clientId, String userId) {

    final AuthenticationContext authContext;
    try {
      authContext = getOrCreateContext(authority);
    } catch (Exception e) {
      callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, e.getMessage()));
      return true;
    }

    authContext.acquireTokenSilent(
        resourceUrl, clientId, userId, new DefaultAuthenticationCallback(callbackContext));
    return true;
  }
 @Test
 public void testAcquireTokenAuthCode_ClientCredential() throws Exception {
   ctx =
       PowerMock.createPartialMock(
           AuthenticationContext.class,
           new String[] {"acquireTokenCommon"},
           TestConfiguration.AAD_TENANT_ENDPOINT,
           true,
           service);
   PowerMock.expectPrivate(
           ctx,
           "acquireTokenCommon",
           EasyMock.isA(AdalAuthorizatonGrant.class),
           EasyMock.isA(ClientAuthentication.class),
           EasyMock.isA(ClientDataHttpHeaders.class))
       .andReturn(
           new AuthenticationResult(
               "bearer",
               "accessToken",
               "refreshToken",
               new Date().getTime(),
               "idToken",
               null,
               false));
   PowerMock.replay(ctx);
   Future<AuthenticationResult> result =
       ctx.acquireTokenByAuthorizationCode(
           "auth_code",
           new URI(TestConfiguration.AAD_DEFAULT_REDIRECT_URI),
           new ClientCredential("clientId", "clientSecret"),
           null);
   AuthenticationResult ar = result.get();
   Assert.assertNotNull(ar);
   PowerMock.verifyAll();
 }
 @Override
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);
   if (currentContext != null) {
     currentContext.onActivityResult(requestCode, resultCode, data);
   }
 }
 @Test(
     expectedExceptions = IllegalArgumentException.class,
     expectedExceptionsMessageRegExp = "credential is null")
 public void testValidateInput_NullCredential() throws MalformedURLException {
   ctx = new AuthenticationContext(TestConfiguration.AAD_TENANT_ENDPOINT, true, service);
   ctx.acquireToken(TestConfiguration.AAD_RESOURCE_ID, (ClientAssertion) null, null);
 }
 @Test(
     expectedExceptions = IllegalArgumentException.class,
     expectedExceptionsMessageRegExp = "resource is null or empty")
 public void testValidateInput_ValidateNullResource() throws MalformedURLException {
   ctx = new AuthenticationContext(TestConfiguration.AAD_TENANT_ENDPOINT, true, service);
   ctx.acquireToken(null, new ClientAssertion("invalid_assertion"), null);
 }
 @Test(
     expectedExceptions = IllegalArgumentException.class,
     expectedExceptionsMessageRegExp = "redirect uri is null")
 public void testAcquireTokenAuthCode_RedirectUriNull() throws Exception {
   ctx = new AuthenticationContext(TestConfiguration.AAD_TENANT_ENDPOINT, true, service);
   ctx.acquireTokenByAuthorizationCode(
       "auth_code", null, new ClientCredential("clientId", "clientSecret"), null);
 }
 @Test(
     expectedExceptions = IllegalArgumentException.class,
     expectedExceptionsMessageRegExp = "clientId is null or empty")
 public void testValidateRefreshTokenRequestInput_NullClientId() throws MalformedURLException {
   ctx = new AuthenticationContext(TestConfiguration.AAD_TENANT_ENDPOINT, true, service);
   ctx.acquireTokenByRefreshToken(
       "refresh_token", null, new ClientAssertion("invalid_assertion"), null);
 }
 @Test(
     expectedExceptions = IllegalArgumentException.class,
     expectedExceptionsMessageRegExp = "authorization code is null or empty")
 public void testcAquireTokenAuthCode_AuthCodeNull() throws Exception {
   ctx = new AuthenticationContext(TestConfiguration.AAD_TENANT_ENDPOINT, true, service);
   ctx.acquireTokenByAuthorizationCode(
       null,
       new URI(TestConfiguration.AAD_DEFAULT_REDIRECT_URI),
       new ClientCredential("clientId", "clientSecret"),
       null);
 }
  private boolean acquireTokenAsync(
      String authority,
      String resourceUrl,
      String clientId,
      String redirectUrl,
      String userId,
      String extraQueryParams) {

    final AuthenticationContext authContext;
    try {
      authContext = getOrCreateContext(authority);
    } catch (Exception e) {
      callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, e.getMessage()));
      return true;
    }

    if (userId != null) {
      ITokenCacheStore cache = authContext.getCache();
      if (cache instanceof ITokenStoreQuery) {

        ArrayList<TokenCacheItem> tokensForUserId =
            ((ITokenStoreQuery) cache).getTokensForUser(userId);
        if (tokensForUserId.size() > 0) {
          // Try to acquire alias for specified userId
          userId = tokensForUserId.get(0).getUserInfo().getDisplayableId();
        }
      }
    }

    authContext.acquireToken(
        this.cordova.getActivity(),
        resourceUrl,
        clientId,
        redirectUrl,
        userId,
        SHOW_PROMPT_ALWAYS,
        extraQueryParams,
        new DefaultAuthenticationCallback(callbackContext));

    return true;
  }
  private boolean deleteTokenCacheItem(
      String authority,
      String itemAuthority,
      String resource,
      String clientId,
      String userId,
      boolean isMultipleResourceRefreshToken) {

    final AuthenticationContext authContext;
    try {
      authContext = getOrCreateContext(authority);
    } catch (Exception e) {
      callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, e.getMessage()));
      return true;
    }

    String key =
        CacheKey.createCacheKey(
            itemAuthority, resource, clientId, isMultipleResourceRefreshToken, userId);
    authContext.getCache().removeItem(key);

    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
    return true;
  }
 @Test
 public void testFailedAcquireTokenRequest_ExecuteCallback() throws Throwable {
   ctx = new AuthenticationContext(TestConfiguration.AAD_UNKNOWN_TENANT_ENDPOINT, true, service);
   AuthenticationCallback ac = PowerMock.createMock(AuthenticationCallback.class);
   ac.onFailure(EasyMock.isA(Throwable.class));
   EasyMock.expectLastCall();
   PowerMock.replay(ac);
   Future<AuthenticationResult> result =
       ctx.acquireTokenByRefreshToken(
           "refresh", new ClientCredential("clientId", "clientSecret"), "resource", ac);
   try {
     result.get();
   } catch (ExecutionException ee) {
     throw ee.getCause();
   }
 }
  @Test
  public void testAcquireTokenAuthCode_KeyCredential() throws Exception {
    ctx =
        PowerMock.createPartialMock(
            AuthenticationContext.class,
            new String[] {"acquireTokenCommon"},
            TestConfiguration.AAD_TENANT_ENDPOINT,
            true,
            service);
    PowerMock.expectPrivate(
            ctx,
            "acquireTokenCommon",
            EasyMock.isA(AdalAuthorizatonGrant.class),
            EasyMock.isA(ClientAuthentication.class),
            EasyMock.isA(ClientDataHttpHeaders.class))
        .andReturn(
            new AuthenticationResult(
                "bearer",
                "accessToken",
                "refreshToken",
                new Date().getTime(),
                "idToken",
                null,
                false));
    final KeyStore keystore = KeyStore.getInstance("PKCS12", "SunJSSE");
    keystore.load(
        new FileInputStream(
            this.getClass().getResource(TestConfiguration.AAD_CERTIFICATE_PATH).getFile()),
        TestConfiguration.AAD_CERTIFICATE_PASSWORD.toCharArray());
    final String alias = keystore.aliases().nextElement();
    final PrivateKey key =
        (PrivateKey)
            keystore.getKey(alias, TestConfiguration.AAD_CERTIFICATE_PASSWORD.toCharArray());
    final X509Certificate cert = (X509Certificate) keystore.getCertificate(alias);

    PowerMock.replay(ctx);
    Future<AuthenticationResult> result =
        ctx.acquireTokenByAuthorizationCode(
            "auth_code",
            new URI(TestConfiguration.AAD_DEFAULT_REDIRECT_URI),
            AsymmetricKeyCredential.create(TestConfiguration.AAD_CLIENT_ID, key, cert),
            null);
    AuthenticationResult ar = result.get();
    Assert.assertNotNull(ar);
    PowerMock.verifyAll();
    PowerMock.resetAll(ctx);
  }
  public void testAcquireToken_Username_Password() throws Exception {
    ctx =
        PowerMock.createPartialMock(
            AuthenticationContext.class,
            new String[] {"acquireTokenCommon"},
            TestConfiguration.AAD_TENANT_ENDPOINT,
            true,
            service);
    PowerMock.expectPrivate(
            ctx,
            "acquireTokenCommon",
            EasyMock.isA(AdalAuthorizatonGrant.class),
            EasyMock.isA(ClientAuthentication.class),
            EasyMock.isA(ClientDataHttpHeaders.class))
        .andReturn(
            new AuthenticationResult(
                "bearer", "accessToken", "refreshToken", new Date().getTime(), null, null, false));

    UserDiscoveryResponse response = EasyMock.createMock(UserDiscoveryResponse.class);
    EasyMock.expect(response.isAccountFederated()).andReturn(false);

    PowerMock.mockStatic(UserDiscoveryRequest.class);
    EasyMock.expect(
            UserDiscoveryRequest.execute(
                EasyMock.isA(String.class),
                EasyMock.isNull(Proxy.class),
                EasyMock.isNull(SSLSocketFactory.class)))
        .andReturn(response);

    PowerMock.replay(ctx, response, UserDiscoveryRequest.class);
    Future<AuthenticationResult> result =
        ctx.acquireToken("resource", "clientId", "username", "password", null);

    AuthenticationResult ar = result.get();
    Assert.assertNotNull(ar);
    PowerMock.verifyAll();
    PowerMock.resetAll(ctx);
  }
 public static void signRequest(HttpRequestBase request, AuthenticationContext context) {
   request.setHeader("Authorization", "Bearer " + context.getAccessToken());
 }
 @Test
 public void testCorrelationId() throws MalformedURLException {
   ctx = new AuthenticationContext(TestConfiguration.AAD_TENANT_ENDPOINT, true, service);
   ctx.setCorrelationId("correlationId");
   Assert.assertEquals(ctx.getCorrelationId(), "correlationId");
 }
  private boolean handleRequestToACSEndpoint(MessageContext messageContext, Session session) {

    String fullResourceURL =
        (String) messageContext.getProperty(RESTConstants.REST_FULL_REQUEST_PATH);

    // Build the incoming message.
    GatewayUtils.buildIncomingMessage(messageContext);

    IDPMessage idpMessage = null;
    try {
      idpMessage = SAMLUtils.processIDPMessage(messageContext);

      if (idpMessage.getSAMLResponse() == null && idpMessage.getSAMLRequest() == null) {
        String errorMessage =
            String.format(
                "A SAML request or response was not there in the request to the ACS URL ('%s')",
                fullResourceURL);
        GatewayUtils.logAndThrowException(log, errorMessage, null);
      }

      if (idpMessage.getRawSAMLResponse() != null) {
        // pass saml response and request for an authorized cookie to access admin services
        String authorizedAdminCookie =
            getAuthenticatedCookieFromIdP(idpMessage.getRawSAMLResponse());
        if (authorizedAdminCookie == null) {
          String errorMessage =
              "Error while requesting the authorized cookie to access IDP admin services via "
                  + "SAML2SSOAuthenticationService";
          GatewayUtils.logAndThrowException(log, errorMessage, null);
        }
        // add to session
        if (session.getAttribute(AppMConstants.IDP_AUTHENTICATED_COOKIE) == null) {
          session.addAttribute(AppMConstants.IDP_AUTHENTICATED_COOKIE, authorizedAdminCookie);
          SessionStore.getInstance().updateSession(session);
        }
      }
    } catch (SAMLException e) {
      String errorMessage =
          String.format(
              "Error while processing the IDP call back request to the ACS URL ('%s')",
              fullResourceURL);
      log.error(errorMessage);
      if (log.isDebugEnabled()) { // Do not log the stack trace without checking isDebugEnabled,
        // because log can be filled by SAML Response XSW attacks.
        log.debug(errorMessage, e);
      }
      GatewayUtils.send401(messageContext, "Unauthorized SAML Response");
      return false;
    }

    GatewayUtils.logWithRequestInfo(
        log,
        messageContext,
        String.format(
            "%s is available in request.",
            idpMessage.getSAMLRequest() != null ? "SAMLRequest" : "SAMLResponse"));

    // If not configured, the SLO request URL and the SLO response URL is the ACS URL by default.
    // SLOResponse is handled in this method. But the SLORequest is handled generically in the rest
    // of the handler code.
    if (idpMessage.isSLOResponse()) {
      GatewayUtils.logWithRequestInfo(log, messageContext, "SAMLResponse in an SLO response.");
      GatewayUtils.redirectToURL(messageContext, GatewayUtils.getAppRootURL(messageContext));
      return false;
    } else if (idpMessage.isSLORequest()) {
      GatewayUtils.logWithRequestInfo(log, messageContext, "SAMLRequest in an SLO request.");
      OMElement response =
          handleSLORequest(messageContext, (LogoutRequest) idpMessage.getSAMLRequest());
      GatewayUtils.send200(messageContext, response);
      return false;
    } else {

      // Validate SAML response validity period
      if (!idpMessage.validateAssertionValidityPeriod()) {
        requestAuthentication(messageContext);
        return false;
      }

      // Validate SAML response signature, assertion signature and audience restrictions
      if (!idpMessage.validateSignatureAndAudienceRestriction(
          idpMessage.getSAMLResponse(), webApp, configuration)) {
        GatewayUtils.send401(messageContext, "Unauthorized SAML Response");
        return false;
      }

      AuthenticationContext authenticationContext =
          getAuthenticationContextFromIDPCallback(idpMessage);

      if (authenticationContext.isAuthenticated()) {;

        if (log.isDebugEnabled()) {
          GatewayUtils.logWithRequestInfo(
              log,
              messageContext,
              String.format(
                  "SAML response is authenticated. Subject = '%s'",
                  authenticationContext.getSubject()));
        }

        session.setAuthenticationContext(authenticationContext);

        if (shouldSendSAMLResponseToBackend()) {

          Map<String, String> samlResponses =
              (Map<String, String>)
                  session.getAttribute(SAMLUtils.SESSION_ATTRIBUTE_RAW_SAML_RESPONSES);

          if (samlResponses == null) {
            samlResponses = new HashMap<String, String>();
            session.addAttribute(SAMLUtils.SESSION_ATTRIBUTE_RAW_SAML_RESPONSES, samlResponses);
          }

          samlResponses.put(webApp.getUUID(), idpMessage.getRawSAMLResponse());
        }

        // Get the SAML session index.
        String sessionIndex =
            (String) SAMLUtils.getSessionIndex((ResponseImpl) idpMessage.getSAMLResponse());
        session.addAttribute(SAMLUtils.SESSION_ATTRIBUTE_SAML_SESSION_INDEX, sessionIndex);
        GatewayUtils.logWithRequestInfo(
            log, messageContext, String.format("Session index : %s", sessionIndex));

        // Add Session Index -> Session ID to a cache.
        CacheManager.getInstance()
            .getSessionIndexMappingCache()
            .put(sessionIndex, session.getUuid());

        // Mark this web app as an access web app in this session.
        session.addAccessedWebAppUUID(webApp.getUUID());

        Map<String, Object> userAttributes =
            getUserAttributes((ResponseImpl) idpMessage.getSAMLResponse());
        session.getAuthenticationContext().setAttributes(userAttributes);

        String roleAttributeValue = (String) userAttributes.get("http://wso2.org/claims/role");

        if (roleAttributeValue != null) {
          String[] roles = roleAttributeValue.split(",");
          for (String role : roles) {
            session.getAuthenticationContext().addRole(role);
          }
        }

        // Generate the JWT and store in the session.
        if (isJWTEnabled()) {
          try {

            // Generate and store the JWT against the app.
            Map<String, String> generatedJWTs =
                (Map<String, String>) session.getAttribute(SESSION_ATTRIBUTE_JWTS);

            if (generatedJWTs == null) {
              generatedJWTs = new HashMap<String, String>();
              session.addAttribute(SESSION_ATTRIBUTE_JWTS, generatedJWTs);
            }

            generatedJWTs.put(
                webApp.getUUID(),
                getJWTGenerator().generateToken(userAttributes, webApp, messageContext));

          } catch (AppManagementException e) {
            String errorMessage =
                String.format(
                    "Can't generate JWT for the subject : '%s'",
                    authenticationContext.getSubject());
            GatewayUtils.logAndThrowException(log, errorMessage, e);
          }
        }

        SessionStore.getInstance().updateSession(session);
        if (session.getRequestedURL() != null) {
          GatewayUtils.redirectToURL(messageContext, session.getRequestedURL());
        } else {
          log.warn(
              String.format(
                  "Original requested URL in the session is null. Redirecting to the app root URL."));
          GatewayUtils.redirectToURL(messageContext, GatewayUtils.getAppRootURL(messageContext));
        }

        return false;
      } else {

        if (log.isDebugEnabled()) {
          GatewayUtils.logWithRequestInfo(
              log, messageContext, "SAML response is not authenticated.");
        }

        requestAuthentication(messageContext);
        return false;
      }
    }
  }
  /**
   * Parses the SecurityToken by wrapping within an AssertionWrapper.
   *
   * @param securityToken SecurityToken
   */
  private void parseToken(SecurityToken securityToken) {
    XMLStreamReader xmlStreamReader = StaxUtils.createXMLStreamReader(securityToken.getToken());

    try {
      AttrStatement attributeStatement = null;
      AuthenticationStatement authenticationStatement = null;
      Attr attribute = null;
      int attrs = 0;
      while (xmlStreamReader.hasNext()) {
        int event = xmlStreamReader.next();
        switch (event) {
          case XMLStreamConstants.START_ELEMENT:
            {
              String localName = xmlStreamReader.getLocalName();
              switch (localName) {
                case NameID.DEFAULT_ELEMENT_LOCAL_NAME:
                  name = xmlStreamReader.getElementText();
                  for (int i = 0; i < xmlStreamReader.getAttributeCount(); i++) {
                    if (xmlStreamReader
                        .getAttributeLocalName(i)
                        .equals(NameID.FORMAT_ATTRIB_NAME)) {
                      nameIDFormat = xmlStreamReader.getAttributeValue(i);
                      break;
                    }
                  }
                  break;
                case AttributeStatement.DEFAULT_ELEMENT_LOCAL_NAME:
                  attributeStatement = new AttrStatement();
                  attributeStatements.add(attributeStatement);
                  break;
                case AuthnStatement.DEFAULT_ELEMENT_LOCAL_NAME:
                  authenticationStatement = new AuthenticationStatement();
                  authenticationStatements.add(authenticationStatement);
                  attrs = xmlStreamReader.getAttributeCount();
                  for (int i = 0; i < attrs; i++) {
                    String name = xmlStreamReader.getAttributeLocalName(i);
                    String value = xmlStreamReader.getAttributeValue(i);
                    if (AuthnStatement.AUTHN_INSTANT_ATTRIB_NAME.equals(name)) {
                      authenticationStatement.setAuthnInstant(DateTime.parse(value));
                    }
                  }
                  break;
                case AuthnContextClassRef.DEFAULT_ELEMENT_LOCAL_NAME:
                  if (authenticationStatement != null) {
                    String classValue = xmlStreamReader.getText();
                    classValue = classValue.trim();
                    AuthenticationContextClassRef authenticationContextClassRef =
                        new AuthenticationContextClassRef();
                    authenticationContextClassRef.setAuthnContextClassRef(classValue);
                    AuthenticationContext authenticationContext = new AuthenticationContext();
                    authenticationContext.setAuthnContextClassRef(authenticationContextClassRef);
                    authenticationStatement.setAuthnContext(authenticationContext);
                  }
                  break;
                case Attribute.DEFAULT_ELEMENT_LOCAL_NAME:
                  attribute = new Attr();
                  if (attributeStatement != null) {
                    attributeStatement.addAttribute(attribute);
                  }
                  attrs = xmlStreamReader.getAttributeCount();
                  for (int i = 0; i < attrs; i++) {
                    String name = xmlStreamReader.getAttributeLocalName(i);
                    String value = xmlStreamReader.getAttributeValue(i);
                    if (Attribute.NAME_ATTTRIB_NAME.equals(name)) {
                      attribute.setName(value);
                    } else if (Attribute.NAME_FORMAT_ATTRIB_NAME.equals(name)) {
                      attribute.setNameFormat(value);
                    }
                  }
                  break;
                case AttributeValue.DEFAULT_ELEMENT_LOCAL_NAME:
                  XSString xsString = new XMLString();
                  xsString.setValue(xmlStreamReader.getElementText());
                  if (attribute != null) {
                    attribute.addAttributeValue(xsString);
                  }
                  break;
                case Issuer.DEFAULT_ELEMENT_LOCAL_NAME:
                  issuer = xmlStreamReader.getElementText();
                  break;
                case Conditions.DEFAULT_ELEMENT_LOCAL_NAME:
                  attrs = xmlStreamReader.getAttributeCount();
                  for (int i = 0; i < attrs; i++) {
                    String name = xmlStreamReader.getAttributeLocalName(i);
                    String value = xmlStreamReader.getAttributeValue(i);
                    if (Conditions.NOT_BEFORE_ATTRIB_NAME.equals(name)) {
                      notBefore = DatatypeConverter.parseDateTime(value).getTime();
                    } else if (Conditions.NOT_ON_OR_AFTER_ATTRIB_NAME.equals(name)) {
                      notOnOrAfter = DatatypeConverter.parseDateTime(value).getTime();
                    }
                  }
                  break;
              }
              break;
            }
          case XMLStreamConstants.END_ELEMENT:
            {
              String localName = xmlStreamReader.getLocalName();
              switch (localName) {
                case AttributeStatement.DEFAULT_ELEMENT_LOCAL_NAME:
                  attributeStatement = null;
                  break;
                case Attribute.DEFAULT_ELEMENT_LOCAL_NAME:
                  attribute = null;
                  break;
              }
              break;
            }
        }
      }
    } catch (XMLStreamException e) {
      LOGGER.error("Unable to parse security token.", e);
    } finally {
      try {
        xmlStreamReader.close();
      } catch (XMLStreamException ignore) {
        // ignore
      }
    }
  }
  @Override
  public boolean handleRequest(MessageContext messageContext) {

    Session session = getSession(messageContext);

    // Get and set relevant message context properties.
    org.apache.axis2.context.MessageContext axis2MessageContext =
        ((Axis2MessageContext) messageContext).getAxis2MessageContext();

    String webAppContext = (String) messageContext.getProperty(RESTConstants.REST_API_CONTEXT);
    String webAppVersion =
        (String) messageContext.getProperty(RESTConstants.SYNAPSE_REST_API_VERSION);
    String fullResourceURL =
        (String) messageContext.getProperty(RESTConstants.REST_FULL_REQUEST_PATH);

    // If the request has come through the default App (the Synapse API without a version),
    // remove the version from the request URL when doing a redirection.
    String redirectionFriendlyFullRequestPath = getRedirectionReadyFullRequestPath(messageContext);
    messageContext.setProperty(
        AppMConstants.MESSAGE_CONTEXT_PROPERTY_REDIRECTION_FRIENDLY_FULL_REQUEST_PATH,
        redirectionFriendlyFullRequestPath);

    String baseURL = String.format("%s/%s/", webAppContext, webAppVersion);
    String relativeResourceURL = StringUtils.substringAfter(fullResourceURL, baseURL);
    String httpVerb = (String) axis2MessageContext.getProperty(Constants.Configuration.HTTP_METHOD);

    // Fetch the web app for the requested context and version.
    try {
      if (webApp == null) {
        int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
        webApp =
            new DefaultAppRepository(null)
                .getWebAppByContextAndVersion(webAppContext, webAppVersion, tenantId);
      }
    } catch (AppManagementException e) {
      String errorMessage =
          String.format("Can't fetch the web for '%s' from the repository.", fullResourceURL);
      GatewayUtils.logAndThrowException(log, errorMessage, e);
    }

    messageContext.setProperty(
        AppMConstants.MESSAGE_CONTEXT_PROPERTY_APP_ID, webApp.getDatabaseId());

    // Find a matched URI template.
    URITemplate matchedTemplate =
        GatewayUtils.findMatchedURITemplate(webApp, httpVerb, relativeResourceURL);
    messageContext.setProperty(
        AppMConstants.MESSAGE_CONTEXT_PROPERTY_MATCHED_URI_TEMPLATE, matchedTemplate);

    // If the request comes to the ACS URL, then it should be a SAML response or a request from the
    // IDP.
    if (isACSURL(relativeResourceURL)) {
      handleRequestToACSEndpoint(messageContext, session);

      // All requests to the ACS URL should be redirected to somewhere. e.g. IDP, app root URL
      return false;
    }

    // Handle logout requests. These requests don't need to  be authenticated.
    if (GatewayUtils.isLogoutURL(webApp, relativeResourceURL)) {
      doLogout(session);
      redirectToIDPWithLogoutRequest(messageContext, session);
      return false;
    }

    if (GatewayUtils.isAnonymousAccessAllowed(webApp, matchedTemplate)) {

      if (log.isDebugEnabled()) {
        GatewayUtils.logWithRequestInfo(
            log,
            messageContext,
            String.format("Request to '%s' is allowed for anonymous access", fullResourceURL));
      }

      messageContext.setProperty(
          AppMConstants.MESSAGE_CONTEXT_PROPERTY_GATEWAY_SKIP_SECURITY, true);
      return true;
    }

    AuthenticationContext authenticationContext = session.getAuthenticationContext();

    if (!authenticationContext.isAuthenticated()) {

      if (log.isDebugEnabled()) {
        GatewayUtils.logWithRequestInfo(
            log,
            messageContext,
            String.format("Request to '%s' is not authenticated", fullResourceURL));
      }

      session.setRequestedURL(redirectionFriendlyFullRequestPath);
      SessionStore.getInstance().updateSession(session);
      setSessionCookie(messageContext, session.getUuid());
      requestAuthentication(messageContext);
      return false;
    } else {

      if (log.isDebugEnabled()) {
        GatewayUtils.logWithRequestInfo(
            log,
            messageContext,
            String.format(
                "Request to '%s' is authenticated. Subject = '%s'",
                fullResourceURL, authenticationContext.getSubject()));
      }

      // If this web app has not been access before in this session, redirect to the IDP.
      // This is done to make sure SLO works.

      if (!session.hasAppBeenAccessedBefore(webApp.getUUID())) {
        GatewayUtils.logWithRequestInfo(
            log,
            messageContext,
            "This web app has not been accessed before in the current session. Doing SSO through IDP since it is needed to make SLO work.");
        session.setRequestedURL(redirectionFriendlyFullRequestPath);
        SessionStore.getInstance().updateSession(session);
        requestAuthentication(messageContext);
        return false;
      }

      // Set the session as a message context property.
      messageContext.setProperty(AppMConstants.APPM_SAML2_COOKIE, session.getUuid());

      if (shouldSendSAMLResponseToBackend()) {

        Map<String, String> samlResponses =
            (Map<String, String>)
                session.getAttribute(SAMLUtils.SESSION_ATTRIBUTE_RAW_SAML_RESPONSES);

        String samlResponseForApp = null;

        if (samlResponses != null
            && (samlResponseForApp = samlResponses.get(webApp.getUUID())) != null) {

          addTransportHeader(messageContext, HTTP_HEADER_SAML_RESPONSE, samlResponseForApp);

          if (log.isDebugEnabled()) {
            GatewayUtils.logWithRequestInfo(
                log, messageContext, "SAML response has been set in the request to the backend.");
          }

        } else {

          if (log.isDebugEnabled()) {
            GatewayUtils.logWithRequestInfo(
                log, messageContext, "Couldn't find the SAML response for the app in the session.");
          }
        }
      }

      if (isJWTEnabled()) {

        String jwtHeaderName =
            configuration.getFirstProperty(APISecurityConstants.API_SECURITY_CONTEXT_HEADER);
        Map<String, String> generatedJWTs =
            (Map<String, String>) session.getAttribute(SESSION_ATTRIBUTE_JWTS);

        String jwtForApp = null;
        if (generatedJWTs != null && (jwtForApp = generatedJWTs.get(webApp.getUUID())) != null) {
          addTransportHeader(messageContext, jwtHeaderName, jwtForApp);
          if (log.isDebugEnabled()) {
            GatewayUtils.logWithRequestInfo(
                log, messageContext, "JWT has been set in the request to the backend.");
          }
        } else {
          if (log.isDebugEnabled()) {
            GatewayUtils.logWithRequestInfo(
                log, messageContext, "Couldn't find the generated JWT for the app in the session.");
          }
        }
      }

      return true;
    }
  }
 @Test(expectedExceptions = AuthenticationException.class)
 public void testInvalidClientAssertion() throws MalformedURLException {
   ctx = new AuthenticationContext(TestConfiguration.AAD_TENANT_ENDPOINT, true, service);
   ctx.acquireToken(
       TestConfiguration.AAD_RESOURCE_ID, new ClientAssertion("invalid_assertion"), null);
 }