@Parameters({"redirectUris", "userId", "userSecret", "redirectUri", "hostnameVerifier"})
  @Test
  public void sessionWorkFlow1(
      final String redirectUris,
      final String userId,
      final String userSecret,
      final String redirectUri,
      String hostnameVerifier)
      throws Exception {
    showTitle("sessionWorkFlow1");

    // Register client
    RegisterRequest registerRequest =
        new RegisterRequest(
            ApplicationType.WEB, "oxAuth test app", StringUtils.spaceSeparatedToList(redirectUris));
    registerRequest.setTokenEndpointAuthMethod(AuthenticationMethod.CLIENT_SECRET_BASIC);

    RegisterClient registerClient = new RegisterClient(registrationEndpoint);
    registerClient.setRequest(registerRequest);
    RegisterResponse registerResponse = registerClient.exec();

    showClient(registerClient);
    assertEquals(
        registerResponse.getStatus(),
        200,
        "Unexpected response code: " + registerResponse.getEntity());
    assertNotNull(registerResponse.getClientId());
    assertNotNull(registerResponse.getClientSecret());
    assertNotNull(registerResponse.getRegistrationAccessToken());
    assertNotNull(registerResponse.getClientIdIssuedAt());
    assertNotNull(registerResponse.getClientSecretExpiresAt());

    String clientId = registerResponse.getClientId();
    String clientSecret = registerResponse.getClientSecret();

    DefaultHttpClient httpClient =
        createHttpClient(HostnameVerifierType.fromString(hostnameVerifier));
    CookieStore cookieStore = new BasicCookieStore();
    httpClient.setCookieStore(cookieStore);
    ClientExecutor clientExecutor = new ApacheHttpClient4Executor(httpClient);

    AuthorizationRequest authorizationRequest1 =
        new AuthorizationRequest(
            Arrays.asList(ResponseType.CODE),
            clientId,
            Arrays.asList("openid", "profile", "email"),
            redirectUri,
            null);

    authorizationRequest1.setAuthUsername(userId);
    authorizationRequest1.setAuthPassword(userSecret);
    authorizationRequest1.getPrompts().add(Prompt.NONE);
    authorizationRequest1.setState("af0ifjsldkj");
    authorizationRequest1.setRequestSessionState(true);

    AuthorizeClient authorizeClient1 = new AuthorizeClient(authorizationEndpoint);
    authorizeClient1.setRequest(authorizationRequest1);
    AuthorizationResponse authorizationResponse1 = authorizeClient1.exec(clientExecutor);

    showClient(authorizeClient1);
    assertEquals(
        authorizationResponse1.getStatus(),
        302,
        "Unexpected response code: " + authorizationResponse1.getStatus());
    assertNotNull(authorizationResponse1.getLocation(), "The location is null");
    assertNotNull(authorizationResponse1.getCode(), "The authorization code is null");
    assertNotNull(authorizationResponse1.getSessionState(), "The session state is null");
    assertNotNull(authorizationResponse1.getState(), "The state is null");
    assertNotNull(authorizationResponse1.getScope(), "The scope is null");

    String code1 = authorizationResponse1.getCode();
    String sessionState = authorizationResponse1.getSessionState();

    // TV sends the code to the Backend
    // We don't use httpClient and cookieStore during this call

    ////////////////////////////////////////////////
    //             Backend  1 side. Code 1        //
    ////////////////////////////////////////////////

    // Get the access token
    TokenClient tokenClient1 = new TokenClient(tokenEndpoint);
    TokenResponse tokenResponse1 =
        tokenClient1.execAuthorizationCode(code1, redirectUri, clientId, clientSecret);

    showClient(tokenClient1);
    assertEquals(
        tokenResponse1.getStatus(), 200, "Unexpected response code: " + tokenResponse1.getStatus());
    assertNotNull(tokenResponse1.getEntity(), "The entity is null");
    assertNotNull(tokenResponse1.getAccessToken(), "The access token is null");
    assertNotNull(tokenResponse1.getExpiresIn(), "The expires in value is null");
    assertNotNull(tokenResponse1.getTokenType(), "The token type is null");
    assertNotNull(tokenResponse1.getRefreshToken(), "The refresh token is null");

    String accessToken1 = tokenResponse1.getAccessToken();

    // Get the user's claims
    UserInfoClient userInfoClient1 = new UserInfoClient(userInfoEndpoint);
    UserInfoResponse userInfoResponse1 = userInfoClient1.execUserInfo(accessToken1);

    showClient(userInfoClient1);
    assertEquals(
        userInfoResponse1.getStatus(),
        200,
        "Unexpected response code: " + userInfoResponse1.getStatus());
    assertNotNull(
        userInfoResponse1.getClaim(JwtClaimName.SUBJECT_IDENTIFIER),
        "Unexpected result: subject not found");
    assertNotNull(
        userInfoResponse1.getClaim(JwtClaimName.NAME), "Unexpected result: name not found");
    assertNotNull(
        userInfoResponse1.getClaim(JwtClaimName.GIVEN_NAME),
        "Unexpected result: given_name not found");
    assertNotNull(
        userInfoResponse1.getClaim(JwtClaimName.FAMILY_NAME),
        "Unexpected result: family_name not found");
    assertNotNull(
        userInfoResponse1.getClaim(JwtClaimName.EMAIL), "Unexpected result: email not found");

    ////////////////////////////////////////////////
    //             TV side. Code 2                //
    ////////////////////////////////////////////////

    AuthorizationRequest authorizationRequest2 =
        new AuthorizationRequest(
            Arrays.asList(ResponseType.CODE),
            clientId,
            Arrays.asList("openid", "profile", "email"),
            redirectUri,
            null);

    authorizationRequest2.getPrompts().add(Prompt.NONE);
    authorizationRequest2.setState("af0ifjsldkj");
    authorizationRequest2.setSessionState(sessionState);

    AuthorizeClient authorizeClient2 = new AuthorizeClient(authorizationEndpoint);
    authorizeClient2.setRequest(authorizationRequest2);
    AuthorizationResponse authorizationResponse2 = authorizeClient2.exec(clientExecutor);

    showClient(authorizeClient2);
    assertEquals(
        authorizationResponse2.getStatus(),
        302,
        "Unexpected response code: " + authorizationResponse2.getStatus());
    assertNotNull(authorizationResponse2.getLocation(), "The location is null");
    assertNotNull(authorizationResponse2.getCode(), "The authorization code is null");
    assertNotNull(authorizationResponse2.getState(), "The state is null");
    assertNotNull(authorizationResponse2.getScope(), "The scope is null");

    String code2 = authorizationResponse2.getCode();

    // TV sends the code to the Backend
    // We don't use httpClient and cookieStore during this call

    ////////////////////////////////////////////////
    //             Backend  2 side. Code 2        //
    ////////////////////////////////////////////////

    // Get the access token
    TokenClient tokenClient2 = new TokenClient(tokenEndpoint);
    TokenResponse tokenResponse2 =
        tokenClient2.execAuthorizationCode(code2, redirectUri, clientId, clientSecret);

    showClient(tokenClient2);
    assertEquals(
        tokenResponse2.getStatus(), 200, "Unexpected response code: " + tokenResponse2.getStatus());
    assertNotNull(tokenResponse2.getEntity(), "The entity is null");
    assertNotNull(tokenResponse2.getAccessToken(), "The access token is null");
    assertNotNull(tokenResponse2.getExpiresIn(), "The expires in value is null");
    assertNotNull(tokenResponse2.getTokenType(), "The token type is null");
    assertNotNull(tokenResponse2.getRefreshToken(), "The refresh token is null");

    String accessToken2 = tokenResponse2.getAccessToken();

    // Get the user's claims
    UserInfoClient userInfoClient2 = new UserInfoClient(userInfoEndpoint);
    UserInfoResponse userInfoResponse2 = userInfoClient2.execUserInfo(accessToken2);

    showClient(userInfoClient2);
    assertEquals(
        userInfoResponse2.getStatus(),
        200,
        "Unexpected response code: " + userInfoResponse2.getStatus());
    assertNotNull(
        userInfoResponse2.getClaim(JwtClaimName.SUBJECT_IDENTIFIER),
        "Unexpected result: subject not found");
    assertNotNull(
        userInfoResponse2.getClaim(JwtClaimName.NAME), "Unexpected result: name not found");
    assertNotNull(
        userInfoResponse2.getClaim(JwtClaimName.GIVEN_NAME),
        "Unexpected result: given_name not found");
    assertNotNull(
        userInfoResponse2.getClaim(JwtClaimName.FAMILY_NAME),
        "Unexpected result: family_name not found");
    assertNotNull(
        userInfoResponse2.getClaim(JwtClaimName.EMAIL), "Unexpected result: email not found");
  }
  @Parameters({"redirectUris", "sectorIdentifierUri", "redirectUri", "userId", "userSecret"})
  @Test // This test requires a place to publish a sector identifier JSON array of redirect URIs via
        // HTTPS
  public void requestAuthorizationCodeWithSectorIdentifier(
      final String redirectUris,
      final String sectorIdentifierUri,
      final String redirectUri,
      final String userId,
      final String userSecret)
      throws Exception {
    showTitle("requestAuthorizationCodeWithSectorIdentifier");

    List<ResponseType> responseTypes = Arrays.asList(ResponseType.CODE, ResponseType.ID_TOKEN);

    // 1. Register client with Sector Identifier URL
    RegisterRequest registerRequest =
        new RegisterRequest(
            ApplicationType.WEB, "oxAuth test app", StringUtils.spaceSeparatedToList(redirectUris));
    registerRequest.addCustomAttribute("oxAuthTrustedClient", "true");
    registerRequest.setResponseTypes(responseTypes);
    registerRequest.setSubjectType(SubjectType.PAIRWISE);
    registerRequest.setSectorIdentifierUri(sectorIdentifierUri);
    registerRequest.setTokenEndpointAuthMethod(AuthenticationMethod.CLIENT_SECRET_POST);

    RegisterClient registerClient = new RegisterClient(registrationEndpoint);
    registerClient.setRequest(registerRequest);
    RegisterResponse registerResponse = registerClient.exec();

    showClient(registerClient);
    assertEquals(
        registerResponse.getStatus(),
        200,
        "Unexpected response code: " + registerResponse.getEntity());
    assertNotNull(registerResponse.getClientId());
    assertNotNull(registerResponse.getClientSecret());
    assertNotNull(registerResponse.getRegistrationAccessToken());
    assertNotNull(registerResponse.getClientSecretExpiresAt());

    String clientId = registerResponse.getClientId();
    String clientSecret = registerResponse.getClientSecret();

    // 2. Request authorization and receive the authorization code.
    List<String> scopes = Arrays.asList("openid", "profile", "address", "email");
    String state = UUID.randomUUID().toString();
    String nonce = UUID.randomUUID().toString();

    AuthorizationRequest authorizationRequest =
        new AuthorizationRequest(responseTypes, clientId, scopes, redirectUri, nonce);
    authorizationRequest.setState(state);
    authorizationRequest.setAuthUsername(userId);
    authorizationRequest.setAuthPassword(userSecret);
    authorizationRequest.getPrompts().add(Prompt.NONE);

    AuthorizeClient authorizeClient = new AuthorizeClient(authorizationEndpoint);
    authorizeClient.setRequest(authorizationRequest);
    AuthorizationResponse authorizationResponse = authorizeClient.exec();

    showClient(authorizeClient);
    assertEquals(
        authorizationResponse.getStatus(),
        302,
        "Unexpected response code: " + authorizationResponse.getStatus());
    assertNotNull(authorizationResponse.getLocation(), "The location is null");
    assertNotNull(authorizationResponse.getCode(), "The authorization code is null");
    assertNotNull(authorizationResponse.getState(), "The state is null");
    assertNotNull(authorizationResponse.getScope(), "The scope is null");
    assertEquals(authorizationResponse.getState(), state);

    String authorizationCode = authorizationResponse.getCode();
    String idToken = authorizationResponse.getIdToken();

    // 3. Validate id_token
    Jwt jwt = Jwt.parse(idToken);
    assertNotNull(jwt.getHeader().getClaimAsString(JwtHeaderName.TYPE));
    assertNotNull(jwt.getHeader().getClaimAsString(JwtHeaderName.ALGORITHM));
    assertNotNull(jwt.getClaims().getClaimAsString(JwtClaimName.SUBJECT_IDENTIFIER));
    assertNotNull(jwt.getClaims().getClaimAsString(JwtClaimName.ISSUER));
    assertNotNull(jwt.getClaims().getClaimAsString(JwtClaimName.AUDIENCE));
    assertNotNull(jwt.getClaims().getClaimAsString(JwtClaimName.EXPIRATION_TIME));
    assertNotNull(jwt.getClaims().getClaimAsString(JwtClaimName.ISSUED_AT));
    assertNotNull(jwt.getClaims().getClaimAsString(JwtClaimName.SUBJECT_IDENTIFIER));
    assertNotNull(jwt.getClaims().getClaimAsString(JwtClaimName.CODE_HASH));
    assertNotNull(jwt.getClaims().getClaimAsString(JwtClaimName.AUTHENTICATION_TIME));

    RSAPublicKey publicKey =
        JwkClient.getRSAPublicKey(jwksUri, jwt.getHeader().getClaimAsString(JwtHeaderName.KEY_ID));
    RSASigner rsaSigner = new RSASigner(SignatureAlgorithm.RS256, publicKey);

    assertTrue(rsaSigner.validate(jwt));

    // 4. Request access token using the authorization code.
    TokenRequest tokenRequest = new TokenRequest(GrantType.AUTHORIZATION_CODE);
    tokenRequest.setCode(authorizationCode);
    tokenRequest.setRedirectUri(redirectUri);
    tokenRequest.setAuthUsername(clientId);
    tokenRequest.setAuthPassword(clientSecret);
    tokenRequest.setAuthenticationMethod(AuthenticationMethod.CLIENT_SECRET_POST);

    TokenClient tokenClient = new TokenClient(tokenEndpoint);
    tokenClient.setRequest(tokenRequest);
    TokenResponse tokenResponse = tokenClient.exec();

    showClient(tokenClient);
    assertEquals(
        tokenResponse.getStatus(), 200, "Unexpected response code: " + tokenResponse.getStatus());
    assertNotNull(tokenResponse.getEntity(), "The entity is null");
    assertNotNull(tokenResponse.getAccessToken(), "The access token is null");
    assertNotNull(tokenResponse.getExpiresIn(), "The expires in value is null");
    assertNotNull(tokenResponse.getTokenType(), "The token type is null");
    assertNotNull(tokenResponse.getRefreshToken(), "The refresh token is null");

    String accessToken = tokenResponse.getAccessToken();

    // 5. Request user info
    UserInfoClient userInfoClient = new UserInfoClient(userInfoEndpoint);
    UserInfoResponse userInfoResponse = userInfoClient.execUserInfo(accessToken);

    showClient(userInfoClient);
    assertEquals(
        userInfoResponse.getStatus(),
        200,
        "Unexpected response code: " + userInfoResponse.getStatus());
    assertNotNull(userInfoResponse.getClaim(JwtClaimName.SUBJECT_IDENTIFIER));
    assertNotNull(userInfoResponse.getClaim(JwtClaimName.NAME));
    assertNotNull(userInfoResponse.getClaim(JwtClaimName.GIVEN_NAME));
    assertNotNull(userInfoResponse.getClaim(JwtClaimName.FAMILY_NAME));
    assertNotNull(userInfoResponse.getClaim(JwtClaimName.EMAIL));
    assertNotNull(userInfoResponse.getClaim(JwtClaimName.ZONEINFO));
    assertNotNull(userInfoResponse.getClaim(JwtClaimName.LOCALE));
  }
  @Parameters({"redirectUris", "redirectUri", "userInum", "userEmail", "hostnameVerifier"})
  @Test
  public void sessionWorkFlow2(
      final String redirectUris,
      final String redirectUri,
      final String userInum,
      final String userEmail,
      final String hostnameVerifier)
      throws Exception {
    showTitle("sessionWorkFlow2");

    // Register client
    RegisterRequest registerRequest =
        new RegisterRequest(
            ApplicationType.WEB, "oxAuth test app", StringUtils.spaceSeparatedToList(redirectUris));
    registerRequest.setTokenEndpointAuthMethod(AuthenticationMethod.CLIENT_SECRET_POST);

    RegisterClient registerClient = new RegisterClient(registrationEndpoint);
    registerClient.setRequest(registerRequest);
    RegisterResponse registerResponse = registerClient.exec();

    showClient(registerClient);
    assertEquals(
        registerResponse.getStatus(),
        200,
        "Unexpected response code: " + registerResponse.getEntity());
    assertNotNull(registerResponse.getClientId());
    assertNotNull(registerResponse.getClientSecret());
    assertNotNull(registerResponse.getRegistrationAccessToken());
    assertNotNull(registerResponse.getClientIdIssuedAt());
    assertNotNull(registerResponse.getClientSecretExpiresAt());

    String clientId = registerResponse.getClientId();
    String clientSecret = registerResponse.getClientSecret();

    DefaultHttpClient httpClient =
        createHttpClient(HostnameVerifierType.fromString(hostnameVerifier));
    CookieStore cookieStore = new BasicCookieStore();
    httpClient.setCookieStore(cookieStore);
    ClientExecutor clientExecutor = new ApacheHttpClient4Executor(httpClient);

    // Authorization code flow to authenticate on B1

    AuthorizationRequest authorizationRequest1 =
        new AuthorizationRequest(
            Arrays.asList(ResponseType.CODE),
            clientId,
            Arrays.asList("openid", "profile", "email"),
            redirectUri,
            null);

    authorizationRequest1.addCustomParameter("mail", userEmail);
    authorizationRequest1.addCustomParameter("inum", userInum);
    authorizationRequest1.getPrompts().add(Prompt.NONE);
    authorizationRequest1.setState("af0ifjsldkj");
    authorizationRequest1.setAuthorizationMethod(AuthorizationMethod.FORM_ENCODED_BODY_PARAMETER);
    authorizationRequest1.setRequestSessionState(true);

    AuthorizeClient authorizeClient1 = new AuthorizeClient(authorizationEndpoint);
    authorizeClient1.setRequest(authorizationRequest1);
    AuthorizationResponse authorizationResponse1 = authorizeClient1.exec(clientExecutor);

    showClient(authorizeClient1);
    assertEquals(
        authorizationResponse1.getStatus(),
        302,
        "Unexpected response code: " + authorizationResponse1.getStatus());
    assertNotNull(authorizationResponse1.getLocation(), "The location is null");
    assertNotNull(authorizationResponse1.getCode(), "The authorization code is null");
    assertNotNull(authorizationResponse1.getSessionState(), "The session id is null");
    assertNotNull(authorizationResponse1.getState(), "The state is null");
    assertNotNull(authorizationResponse1.getScope(), "The scope is null");

    String authorizationCode1 = authorizationResponse1.getCode();
    String sessionState = authorizationResponse1.getSessionState();

    TokenRequest tokenRequest1 = new TokenRequest(GrantType.AUTHORIZATION_CODE);
    tokenRequest1.setCode(authorizationCode1);
    tokenRequest1.setRedirectUri(redirectUri);
    tokenRequest1.setAuthUsername(clientId);
    tokenRequest1.setAuthPassword(clientSecret);
    tokenRequest1.setAuthenticationMethod(AuthenticationMethod.CLIENT_SECRET_POST);

    TokenClient tokenClient1 = new TokenClient(tokenEndpoint);
    tokenClient1.setRequest(tokenRequest1);
    TokenResponse tokenResponse1 = tokenClient1.exec();

    showClient(tokenClient1);
    assertEquals(
        tokenResponse1.getStatus(), 200, "Unexpected response code: " + tokenResponse1.getStatus());
    assertNotNull(tokenResponse1.getEntity(), "The entity is null");
    assertNotNull(tokenResponse1.getAccessToken(), "The access token is null");
    assertNotNull(tokenResponse1.getExpiresIn(), "The expires in value is null");
    assertNotNull(tokenResponse1.getTokenType(), "The token type is null");
    assertNotNull(tokenResponse1.getRefreshToken(), "The refresh token is null");

    // User wants to authenticate on B2 (without sending its credentials)

    AuthorizationRequest authorizationRequest2 =
        new AuthorizationRequest(
            Arrays.asList(ResponseType.CODE),
            clientId,
            Arrays.asList("openid", "profile", "email"),
            redirectUri,
            null);

    authorizationRequest2.getPrompts().add(Prompt.NONE);
    authorizationRequest2.setState("af0ifjsldkj");
    authorizationRequest2.setSessionState(sessionState);

    AuthorizeClient authorizeClient2 = new AuthorizeClient(authorizationEndpoint);
    authorizeClient2.setRequest(authorizationRequest2);
    AuthorizationResponse authorizationResponse2 = authorizeClient2.exec(clientExecutor);

    showClient(authorizeClient2);
    assertEquals(
        authorizationResponse2.getStatus(),
        302,
        "Unexpected response code: " + authorizationResponse2.getStatus());
    assertNotNull(authorizationResponse2.getLocation(), "The location is null");
    assertNotNull(authorizationResponse2.getCode(), "The authorization code is null");
    assertNotNull(authorizationResponse2.getState(), "The state is null");
    assertNotNull(authorizationResponse2.getScope(), "The scope is null");

    String authorizationCode2 = authorizationResponse2.getCode();

    TokenRequest tokenRequest2 = new TokenRequest(GrantType.AUTHORIZATION_CODE);
    tokenRequest2.setCode(authorizationCode2);
    tokenRequest2.setRedirectUri(redirectUri);
    tokenRequest2.setAuthUsername(clientId);
    tokenRequest2.setAuthPassword(clientSecret);
    tokenRequest2.setAuthenticationMethod(AuthenticationMethod.CLIENT_SECRET_POST);

    TokenClient tokenClient2 = new TokenClient(tokenEndpoint);
    tokenClient2.setRequest(tokenRequest2);
    TokenResponse tokenResponse2 = tokenClient2.exec();

    showClient(tokenClient2);
    assertEquals(
        tokenResponse2.getStatus(), 200, "Unexpected response code: " + tokenResponse2.getStatus());
    assertNotNull(tokenResponse2.getEntity(), "The entity is null");
    assertNotNull(tokenResponse2.getAccessToken(), "The access token is null");
    assertNotNull(tokenResponse2.getExpiresIn(), "The expires in value is null");
    assertNotNull(tokenResponse2.getTokenType(), "The token type is null");
    assertNotNull(tokenResponse2.getRefreshToken(), "The refresh token is null");

    // User wants to authenticate on B3 (without sending its credentials)

    AuthorizationRequest authorizationRequest3 =
        new AuthorizationRequest(
            Arrays.asList(ResponseType.CODE),
            clientId,
            Arrays.asList("openid", "profile", "email"),
            redirectUri,
            null);

    authorizationRequest3.getPrompts().add(Prompt.NONE);
    authorizationRequest3.setState("af0ifjsldkj");
    authorizationRequest3.setSessionState(sessionState);

    AuthorizeClient authorizeClient3 = new AuthorizeClient(authorizationEndpoint);
    authorizeClient3.setRequest(authorizationRequest3);
    AuthorizationResponse authorizationResponse3 = authorizeClient2.exec(clientExecutor);

    showClient(authorizeClient3);
    assertEquals(
        authorizationResponse3.getStatus(),
        302,
        "Unexpected response code: " + authorizationResponse3.getStatus());
    assertNotNull(authorizationResponse3.getLocation(), "The location is null");
    assertNotNull(authorizationResponse3.getCode(), "The authorization code is null");
    assertNotNull(authorizationResponse3.getState(), "The state is null");
    assertNotNull(authorizationResponse3.getScope(), "The scope is null");

    String authorizationCode3 = authorizationResponse3.getCode();

    TokenRequest tokenRequest3 = new TokenRequest(GrantType.AUTHORIZATION_CODE);
    tokenRequest3.setCode(authorizationCode3);
    tokenRequest3.setRedirectUri(redirectUri);
    tokenRequest3.setAuthUsername(clientId);
    tokenRequest3.setAuthPassword(clientSecret);
    tokenRequest3.setAuthenticationMethod(AuthenticationMethod.CLIENT_SECRET_POST);

    TokenClient tokenClient3 = new TokenClient(tokenEndpoint);
    tokenClient3.setRequest(tokenRequest3);
    TokenResponse tokenResponse3 = tokenClient3.exec();

    showClient(tokenClient3);
    assertEquals(
        tokenResponse3.getStatus(), 200, "Unexpected response code: " + tokenResponse3.getStatus());
    assertNotNull(tokenResponse3.getEntity(), "The entity is null");
    assertNotNull(tokenResponse3.getAccessToken(), "The access token is null");
    assertNotNull(tokenResponse3.getExpiresIn(), "The expires in value is null");
    assertNotNull(tokenResponse3.getTokenType(), "The token type is null");
    assertNotNull(tokenResponse3.getRefreshToken(), "The refresh token is null");
  }