feat(cognito): show the client's identity providers on the hosted login page
The hosted login page now offers a "Continue with <provider>" button for each of the app client's other SupportedIdentityProviders, carrying the same authorize parameters (state, nonce, PKCE) into the federated flow, as Cognito's managed login does. A client that lists only external providers gets the buttons without the password form instead of an error.
This commit is contained in:
+23
-1
@@ -23,6 +23,7 @@ import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@@ -171,11 +172,32 @@ class CognitoHostedLoginIntegrationTest {
|
||||
"AllowedOAuthFlows":["code"],"AllowedOAuthScopes":["openid"],"CallbackURLs":["%s"],
|
||||
"SupportedIdentityProviders":["CompanyIdp"]}
|
||||
""".formatted(poolId, CALLBACK)).path("UserPoolClient").path("ClientId").asText();
|
||||
given().redirects().follow(false)
|
||||
String federatedLogin = given().redirects().follow(false)
|
||||
.queryParam("client_id", federatedOnly).queryParam("redirect_uri", CALLBACK).queryParam("response_type", "code")
|
||||
.queryParam("state", "app-state")
|
||||
.when().get("/cognito-idp/oauth2/authorize")
|
||||
.then().statusCode(302).extract().header("Location");
|
||||
String federatedPage = given().redirects().follow(false).urlEncodingEnabled(false).get(federatedLogin)
|
||||
.then().statusCode(200).extract().asString();
|
||||
assertTrue(federatedPage.contains(">Continue with CompanyIdp</a>"), federatedPage);
|
||||
assertTrue(federatedPage.contains("identity_provider=CompanyIdp"), "the button starts the federated flow");
|
||||
assertTrue(federatedPage.contains("state=app-state"), "the button keeps the app's authorize parameters");
|
||||
assertFalse(federatedPage.contains("name=\"password\""), "no password form without COGNITO");
|
||||
given().redirects().follow(false)
|
||||
.formParam("client_id", federatedOnly).formParam("redirect_uri", CALLBACK).formParam("response_type", "code")
|
||||
.formParam("username", email).formParam("password", PASSWORD)
|
||||
.when().post("/cognito-idp/login")
|
||||
.then().statusCode(400).body(containsString("COGNITO is not one of its identity providers"));
|
||||
|
||||
cognitoJson("UpdateUserPoolClient", """
|
||||
{"UserPoolId":"%s","ClientId":"%s","ClientName":"hosted-web","AllowedOAuthFlowsUserPoolClient":true,
|
||||
"AllowedOAuthFlows":["code"],"AllowedOAuthScopes":["openid","email"],
|
||||
"CallbackURLs":["%s"],"LogoutURLs":["%s"],"SupportedIdentityProviders":["COGNITO","CompanyIdp"],
|
||||
"ExplicitAuthFlows":["ALLOW_REFRESH_TOKEN_AUTH"]}
|
||||
""".formatted(poolId, clientId, CALLBACK, SIGNED_OUT));
|
||||
String both = loginPage().asString();
|
||||
assertTrue(both.contains("name=\"password\"") && both.contains(">Continue with CompanyIdp</a>"), both);
|
||||
|
||||
given().redirects().follow(false)
|
||||
.queryParam("client_id", clientId).queryParam("redirect_uri", CALLBACK).queryParam("response_type", "code")
|
||||
.queryParam("code_challenge", "abc").queryParam("code_challenge_method", "plain")
|
||||
|
||||
Reference in New Issue
Block a user