dhulipudi / webextest

test
0 stars 0 forks source link

authentication test #7

Open dhulipudi opened 2 months ago

dhulipudi commented 2 months ago

import org.apache.sling.jcr.api.SlingRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations;

import javax.jcr.Session; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;

import static org.junit.jupiter.api.Assertions.; import static org.mockito.Mockito.; import javax.jcr.SimpleCredentials; import org.apache.sling.auth.core.spi.AuthenticationInfo; import org.apache.jackrabbit.api.security.authentication.token.TokenCredentials;

public class WFAuthenticationHandlerTest {

@Mock
private HttpServletRequest request;

@Mock
private HttpServletResponse response;

@Mock
private SlingRepository repository;

@Mock
private Session session;

@Mock
private WFLoginCallback loginCallback;

@InjectMocks
private WFAuthenticationHandler handler;
private static final String TOKEN_ID = ".token";

@BeforeEach
public void setup() {
    MockitoAnnotations.openMocks(this);
}

@Test
public void testExtractCredentials_ValidCredentials() throws Exception {
    String username = "testuser";
    String password = "testpassword";
    String token = "testtoken";

    // Spy the syste under test
    handler = spy(handler);

    // Bypass Token Cookie Update
    doNothing().when(handler).updateTokenCookie(any(HttpServletRequest.class), any(HttpServletResponse.class), anyString(), any(TokenCredentials.class), any(SlingRepository.class));

    when(request.getParameter("j_username")).thenReturn(username);
    when(request.getParameter("j_password")).thenReturn(password);
    when(request.getRequestURI()).thenReturn("/j_security_check");

    SimpleCredentials creds = new SimpleCredentials(username, password.toCharArray());
    creds.setAttribute(TOKEN_ID, token);

    when(repository.login(any(SimpleCredentials.class))).thenReturn(session);
    when(repository.getDescriptor("crx.cluster.id")).thenReturn("mockRepoId");

    // Mock the token generation process
    when(session.getAttribute(TOKEN_ID)).thenReturn(token);

    AuthenticationInfo authInfo = handler.extractCredentials(request, response);

    assertNotNull(authInfo);
    assertEquals("TOKEN", authInfo.getAuthType());
    assertEquals(username, authInfo.getUser());
    assertTrue(authInfo.get("user.jcr.credentials") instanceof TokenCredentials);
}

@Test
public void testExtractCredentials_ValidCredentialsA() throws Exception {
    String username = "testuser";
    String password = "testpassword";
    String token = "testtoken";

    // Spy the syste under test
    handler = spy(handler);

    // Bypass Token Cookie Update
    doNothing().when(handler).updateTokenCookie(any(HttpServletRequest.class), any(HttpServletResponse.class), anyString(), any(TokenCredentials.class), any(SlingRepository.class));

    when(request.getParameter("j_username")).thenReturn(username);
    when(request.getParameter("j_password")).thenReturn(password);
    when(request.getRequestURI()).thenReturn("/j_security_check");

    SimpleCredentials creds = new SimpleCredentials(username, password.toCharArray());
    creds.setAttribute(TOKEN_ID, token);

    when(repository.login(any(SimpleCredentials.class))).thenReturn(session);
    when(repository.getDescriptor("crx.cluster.id")).thenReturn("mockRepoId");

    // Mock the token generation process
    when(session.getAttribute(TOKEN_ID)).thenReturn(token);

    AuthenticationInfo authInfo = handler.extractCredentials(request, response);

    assertNotNull(authInfo);
    assertEquals("TOKEN", authInfo.getAuthType());
    assertEquals(username, authInfo.getUser());
    assertTrue(authInfo.get("user.jcr.credentials") instanceof TokenCredentials);
}}
dhulipudi commented 2 months ago

import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.stream.Stream;

import javax.jcr.LoginException; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.SimpleCredentials; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils; import org.apache.jackrabbit.api.security.authentication.token.TokenCredentials; import org.apache.sling.auth.core.spi.AuthenticationFeedbackHandler; import org.apache.sling.auth.core.spi.AuthenticationHandler; import org.apache.sling.auth.core.spi.AuthenticationInfo; import org.apache.sling.auth.core.spi.DefaultAuthenticationFeedbackHandler; import org.apache.sling.jcr.api.SlingRepository; import org.apache.sling.auth.core.AuthUtil; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.osgi.service.metatype.annotations.AttributeDefinition; import org.osgi.service.metatype.annotations.Designate; import org.osgi.service.metatype.annotations.ObjectClassDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory;

import com.day.crx.security.token.TokenCookie;

import static org.apache.sling.auth.core.spi.AuthenticationHandler.TYPE_PROPERTY; import static org.apache.sling.auth.core.spi.AuthenticationHandler.PATH_PROPERTY; import static org.osgi.framework.Constants.SERVICE_DESCRIPTION; import static org.osgi.framework.Constants.SERVICE_RANKING; import static org.osgi.service.component.annotations.ReferenceCardinality.MULTIPLE; import static org.osgi.service.component.annotations.ReferencePolicy.DYNAMIC; import static org.apache.commons.lang3.StringUtils.EMPTY;

/**

@Component(service = { AuthenticationHandler.class, AuthenticationFeedbackHandler.class }, // configurationPolicy = REQUIRE, property = { PATH_PROPERTY + "=/content", TYPE_PROPERTY + "= WF_OAUTH", SERVICE_DESCRIPTION + "= WellsFargo Federated Authenticator", SERVICE_RANKING + ":Integer=80000" }) public class WFAuthenticationHandler extends DefaultAuthenticationFeedbackHandler implements AuthenticationHandler {

private static final Logger LOGGER = LoggerFactory.getLogger(WFAuthenticationHandler.class);

@ObjectClassDefinition(name = "CWA AuthenticationHandler Configuration", description = "Configuration for CWA AuthenticationHandler.")
public @interface Config {

    @AttributeDefinition(name = "WF AuthenticationHandler Paths")
    String[] path() default { "/content/brandcentral" };

    @AttributeDefinition(name = "Auth Request Url")
    String cwaAuthRequestUrl() default "";

    @AttributeDefinition(name = "Callback Url")
    String cwaCallbackUrl() default "";

    @AttributeDefinition(name = "SessionManager Callback Url")
    String sessionManagerCallbackUrl() default "";

    @AttributeDefinition(name = "SessionManager Logout Url")
    String sessionManagerLogoutUrl() default "";

    @AttributeDefinition(name = "SessionManager UserInfo Url")
    String sessionManagerUserInfoUrl() default "";
}

private Config config;

private final String REQUEST_METHOD = "GET";
private final String USER_NAME = "j_username";
private final String PASSWORD = "j_password";
private static final String TOKEN_ID = ".token";
private final ConcurrentMap<String, WFLoginCallback> callbacks = new ConcurrentHashMap<>();

@Reference SlingRepository repository;
/**
 * This method is used to extract credentials from the request.
 * @param request This is the first parameter to extractCredentials method
 * @param response  This is the second parameter to extractCredentials method
 * @return AuthenticationInfo This returns an instance of AuthenticationInfo.
 */
@Override
public AuthenticationInfo extractCredentials(HttpServletRequest request, HttpServletResponse response) {
    LOGGER.info("extractCredentials");
    AuthenticationInfo authenticationInfo = null;
    String j_username = request.getParameter(USER_NAME);
    String j_password = request.getParameter(PASSWORD);
    if ((request.getRequestURI().contains("j_security_check"))) {
        try {
            authenticationInfo = basicAuth(request, response, j_username, j_password);
        } catch (LoginException ex) {
            LOGGER.error(ex.getMessage());
            return null;
        }
    }
    return authenticationInfo;
}

private AuthenticationInfo basicAuth(HttpServletRequest request, HttpServletResponse response,
        String userName, String password) throws LoginException {
    AuthenticationInfo authInfo = null;
    if ((userName != null && password != null)) {
        authInfo = new AuthenticationInfo("TOKEN", userName);
        SimpleCredentials creds = new SimpleCredentials(userName,
                password.toCharArray());
        Session session = null;
        try {
            session = this.repository.login(creds);
            this.repository.login(creds);
            if (session != null) {
                // create a new AuthenticationInfo object that makes use of the standard
                // AEM token authentication
                authInfo = new AuthenticationInfo("TOKEN",
                        userName);
                // and we set a dummy token which will be updated
                creds.setAttribute(TOKEN_ID, "testtoken");

                // log in using the credentials to record the log in event
                repository.login(creds);

                // use the associated session to create TokenCredentials
                TokenCredentials tc = new TokenCredentials((String) creds.getAttribute(TOKEN_ID));
                // and set the token-credentials in authenticationInfo object
                authInfo.put("user.jcr.credentials", tc);

                // set or update login token cookie
                String repoId = repository.getDescriptor("crx.cluster.id");
                // TokenCookie.update(request, response, repoId, tc.getToken(),
                //         repository.getDefaultWorkspace(), true);
                updateTokenCookie(request, response, repoId, tc, repository);
                if (session.isLive()) {
                    session.logout();
                }
                LOGGER.info("authInfo:{}", authInfo);
                return authInfo;
            }
        } catch (LoginException e) {
            LOGGER.error(
                    this.getClass().getName() + " extractCredentials(..) Failed to log user in" + e.getMessage(),
                    e);
            e.printStackTrace();
        } catch (RepositoryException e) {
            LOGGER.error(
                    this.getClass().getName() + " extractCredentials(..) Failed to log user in" + e.getMessage(),
                    e);
        }
    }
    return authInfo;
}

// Helper method to update the token cookie, to make this unit testable
public void updateTokenCookie(HttpServletRequest request, HttpServletResponse response, String repoId, TokenCredentials tc, SlingRepository repository) {
    TokenCookie.update(request, response, repoId, tc.getToken(),
                        repository.getDefaultWorkspace(), true);
}

@Override
public boolean requestCredentials(HttpServletRequest request, HttpServletResponse response) throws IOException {
    return false;
}

@Override
public void dropCredentials(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String appId = request.getParameter("appId");
    LOGGER.info("dropCredentials for appId: [{}]", appId);
    if (StringUtils.isNotEmpty(appId)) {
        if (Boolean.parseBoolean(request.getParameter("sm"))) {
            LOGGER.info("Sending AppId: [{}] to SessionManager for logout.", appId);
            this.redirect(response, this.config.sessionManagerLogoutUrl() + "?appId=" + appId, true);
        } else {
            this.redirect(response, "/bin/public/servlets/cwa/logout?appId=" + appId, true);
        }
    }
}

// <<----------------------------------- AuthenticationFeedbackHandler
// ----------------------------------->>

@Override
public void authenticationFailed(HttpServletRequest request, HttpServletResponse response,
        AuthenticationInfo authInfo) {
    LOGGER.info("authenticationFailed");
    this.callbacks.forEach((name, callback) -> {
        try {
            if (callback.canHandle(request)) {
                callback.onLoginFailure(request);
            }
        } catch (Exception ex) {
            LOGGER.error(ex.getMessage(), ex);
        }
    });
}

@Override
public boolean authenticationSucceeded(HttpServletRequest request, HttpServletResponse response,
        AuthenticationInfo authInfo) {
    LOGGER.info("authenticationSucceeded");
    this.callbacks.forEach((name, callback) -> {
        try {
            LOGGER.info("Name:{}", name);
            if (callback.canHandle(request)) {
                callback.onLoginSuccess(request);
            }
        } catch (Exception ex) { // NOSONAR
            LOGGER.error(ex.getMessage(), ex);
        }
    });
    // return true so that SlingAuthenticator stops further request processing and
    // redirect to the given url instead.
    return redirectQuietly(response, AuthUtil.getLoginResource(request, EMPTY), false);
}

@Reference(service = WFLoginCallback.class, cardinality = MULTIPLE, policy = DYNAMIC)
protected void bindCWALoginCallback(WFLoginCallback callback) {
    this.callbacks.put(callback.getTenantName(), callback);
    LOGGER.info("Added [{}] WFLoginCallback!", callback.getTenantName());
}

protected void unbindCWALoginCallback(WFLoginCallback callback) {
    if (this.callbacks.remove(callback.getTenantName()) != null) {
        LOGGER.info("Removed [{}] WFLoginCallback!", callback.getTenantName());
    }
}

private boolean redirectQuietly(HttpServletResponse resp, String url, boolean encodeUrl) {
    boolean outcome = false;
    try {
        if (resp.isCommitted()) {
            LOGGER.error("Response already committed!!");
        } else {
            LOGGER.debug("Redirecting to url: [{}]", url);
            resp.sendRedirect(encodeUrl ? resp.encodeRedirectURL(url) : url);
            outcome = true;
        }
    } catch (IOException ex) {
        LOGGER.error(ex.getMessage(), ex);// NOSONAR
    }
    return outcome;
}

private void redirect(HttpServletResponse resp, String url, boolean encodeUrl) throws IOException {
    LOGGER.debug("Redirecting to: [{}]", url);
    resp.sendRedirect(encodeUrl ? resp.encodeRedirectURL(url) : url);
}

@Activate
protected void start(Config config) {
    this.config = config;
    Stream.of(config.path())
            .forEach(path -> LOGGER.info("WFAuthenticationHandler listening at path: [{}]", path));
}

}