mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-25 16:42:34 +00:00
Fixes #10701 Signed-off-by: Thomas Darimont <thomas.darimont@googlemail.com>
This commit is contained in:
@@ -73,6 +73,9 @@ public class OIDCConfigurationRepresentation {
|
||||
@JsonProperty("subject_types_supported")
|
||||
private List<String> subjectTypesSupported;
|
||||
|
||||
@JsonProperty("prompt_values_supported")
|
||||
private List<String> promptValuesSupported;
|
||||
|
||||
@JsonProperty("id_token_signing_alg_values_supported")
|
||||
private List<String> idTokenSigningAlgValuesSupported;
|
||||
|
||||
@@ -655,4 +658,11 @@ public class OIDCConfigurationRepresentation {
|
||||
this.authorizationResponseIssParameterSupported = authorizationResponseIssParameterSupported;
|
||||
}
|
||||
|
||||
public List<String> getPromptValuesSupported() {
|
||||
return promptValuesSupported;
|
||||
}
|
||||
|
||||
public void setPromptValuesSupported(List<String> promptValuesSupported) {
|
||||
this.promptValuesSupported = promptValuesSupported;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,7 +419,8 @@ Sometimes it can be useful for the client application to directly redirect the u
|
||||
user clicks *Register* or *Forget password* on the normal login screen. Automatic redirect to the registration or reset-credentials screen can be done as follows:
|
||||
|
||||
* When the client wants the user to be redirected directly to the registration, the OIDC client should replace the very last snippet from the OIDC login URL path (`/auth`) with `/registrations` . So the full URL
|
||||
might be similar to the following: `https://keycloak.example.com/realms/your_realm/protocol/openid-connect/registrations`.
|
||||
might be similar to the following: `https://keycloak.example.com/realms/your_realm/protocol/openid-connect/registrations`. As an alternative to using the `/registrations` endpoint, clients can use the OIDC
|
||||
`prompt` parameter with `prompt=create` to redirect the user to the registration.
|
||||
|
||||
* When the client wants a user to be redirected directly to the `Reset credentials` flow, the OIDC client should replace the very last snippet from the OIDC login URL path (`/auth`) with `/forgot-credentials` .
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
|
||||
public static final String PROMPT_VALUE_NONE = "none";
|
||||
public static final String PROMPT_VALUE_LOGIN = "login";
|
||||
public static final String PROMPT_VALUE_CONSENT = "consent";
|
||||
public static final String PROMPT_VALUE_CREATE = "create";
|
||||
public static final String PROMPT_VALUE_SELECT_ACCOUNT = "select_account";
|
||||
|
||||
// Client authentication methods
|
||||
|
||||
@@ -91,6 +91,9 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
|
||||
// KEYCLOAK-7451 OAuth Authorization Server Metadata for Proof Key for Code Exchange
|
||||
public static final List<String> DEFAULT_CODE_CHALLENGE_METHODS_SUPPORTED = list(OAuth2Constants.PKCE_METHOD_PLAIN, OAuth2Constants.PKCE_METHOD_S256);
|
||||
|
||||
// See: GH-10701, note that the supported prompt value "create" is only added if the realm supports registrations.
|
||||
public static final List<String> DEFAULT_PROMPT_VALUES_SUPPORTED = list(OIDCLoginProtocol.PROMPT_VALUE_NONE /*, OIDCLoginProtocol.PROMPT_VALUE_CREATE*/, OIDCLoginProtocol.PROMPT_VALUE_LOGIN, OIDCLoginProtocol.PROMPT_VALUE_CONSENT);
|
||||
|
||||
private final KeycloakSession session;
|
||||
private final Map<String, Object> openidConfigOverride;
|
||||
private final boolean includeClientScopes;
|
||||
@@ -167,6 +170,8 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
|
||||
config.setGrantTypesSupported(DEFAULT_GRANT_TYPES_SUPPORTED);
|
||||
config.setAcrValuesSupported(getAcrValuesSupported(realm));
|
||||
|
||||
config.setPromptValuesSupported(getPromptValuesSupported(realm));
|
||||
|
||||
config.setTokenEndpointAuthMethodsSupported(getClientAuthMethodsSupported());
|
||||
config.setTokenEndpointAuthSigningAlgValuesSupported(getSupportedClientSigningAlgorithms(false));
|
||||
config.setIntrospectionEndpointAuthMethodsSupported(getClientAuthMethodsSupported());
|
||||
@@ -235,6 +240,14 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
|
||||
return config;
|
||||
}
|
||||
|
||||
protected List<String> getPromptValuesSupported(RealmModel realm) {
|
||||
List<String> prompts = new ArrayList<>(DEFAULT_PROMPT_VALUES_SUPPORTED);
|
||||
if (realm.isRegistrationAllowed()) {
|
||||
prompts.add(OIDCLoginProtocol.PROMPT_VALUE_CREATE);
|
||||
}
|
||||
return prompts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@@ -204,6 +204,16 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
|
||||
|
||||
// So back button doesn't work
|
||||
CacheControlUtil.noBackButtonCacheControlHeader(session);
|
||||
|
||||
// Add support for Initiating User Registration via OpenID Connect 1.0 via prompt=create
|
||||
// see: https://openid.net/specs/openid-connect-prompt-create-1_0.html#section-4.1
|
||||
if (OIDCLoginProtocol.PROMPT_VALUE_CREATE.equals(params.getFirst(OAuth2Constants.PROMPT))) {
|
||||
if (!Organizations.isRegistrationAllowed(session, realm)) {
|
||||
throw new ErrorPageException(session, authenticationSession, Response.Status.BAD_REQUEST, Messages.REGISTRATION_NOT_ALLOWED);
|
||||
}
|
||||
return buildRegister();
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case REGISTER:
|
||||
return buildRegister();
|
||||
|
||||
@@ -80,7 +80,9 @@ import org.keycloak.testsuite.pages.AppPage;
|
||||
import org.keycloak.testsuite.pages.ErrorPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.pages.OAuthGrantPage;
|
||||
import org.keycloak.testsuite.pages.RegisterPage;
|
||||
import org.keycloak.testsuite.rest.resource.TestingOIDCEndpointsApplicationResource;
|
||||
import org.keycloak.testsuite.util.RealmManager;
|
||||
import org.keycloak.util.JWKSUtils;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
@@ -124,6 +126,9 @@ public class OIDCAdvancedRequestParamsTest extends AbstractTestRealmKeycloakTest
|
||||
@Page
|
||||
protected AppPage appPage;
|
||||
|
||||
@Page
|
||||
protected RegisterPage registerPage;
|
||||
|
||||
@Page
|
||||
protected LoginPage loginPage;
|
||||
|
||||
@@ -406,6 +411,35 @@ public class OIDCAdvancedRequestParamsTest extends AbstractTestRealmKeycloakTest
|
||||
Assert.assertEquals(oldIdToken.getSessionState(), newIdToken.getSessionState());
|
||||
}
|
||||
|
||||
// prompt=create
|
||||
@Test
|
||||
public void promptCreate() {
|
||||
|
||||
// Assert registration page with prompt=login
|
||||
driver.navigate().to(oauth.getLoginFormUrl() + "&prompt=create");
|
||||
registerPage.assertCurrent();
|
||||
}
|
||||
|
||||
// prompt=create
|
||||
@Test
|
||||
public void promptCreateShouldFailWhenRegistrationsAreDisabled() {
|
||||
|
||||
RealmRepresentation realmRep = adminClient.realm("test").toRepresentation();
|
||||
Boolean registrationAllowed = realmRep.isRegistrationAllowed();
|
||||
realmRep.setRegistrationAllowed(false);
|
||||
adminClient.realm("test").update(realmRep);
|
||||
|
||||
// Assert registration page with prompt=login
|
||||
try {
|
||||
driver.navigate().to(oauth.getLoginFormUrl() + "&prompt=create");
|
||||
errorPage.assertCurrent();
|
||||
assertTrue(errorPage.getError().contains("Registration not allowed"));
|
||||
} finally {
|
||||
realmRep.setRegistrationAllowed(registrationAllowed);
|
||||
adminClient.realm("test").update(realmRep);
|
||||
}
|
||||
}
|
||||
|
||||
// prompt=consent
|
||||
@Test
|
||||
public void promptConsent() {
|
||||
|
||||
Reference in New Issue
Block a user