Merge pull request #3059 from mposolda/master
KEYCLOAK-3354 request and request_uri not supported
This commit is contained in:
commit
a73dd537f3
8 changed files with 137 additions and 3 deletions
|
@ -29,11 +29,13 @@ public class OAuthErrorException extends Exception {
|
|||
public static final String ACCESS_DENIED = "access_denied";
|
||||
public static final String UNSUPPORTED_RESPONSE_TYPE = "unsupported_response_type";
|
||||
public static final String SERVER_ERROR = "server_error";
|
||||
public static final String TEMPORARILY_UNAVAILABKE = "temporarily_unavailable";
|
||||
public static final String TEMPORARILY_UNAVAILABLE = "temporarily_unavailable";
|
||||
|
||||
// OpenID Connect 1
|
||||
public static final String INTERACTION_REQUIRED = "interaction_required";
|
||||
public static final String LOGIN_REQUIRED = "login_required";
|
||||
public static final String REQUEST_NOT_SUPPORTED = "request_not_supported";
|
||||
public static final String REQUEST_URI_NOT_SUPPORTED = "request_uri_not_supported";
|
||||
|
||||
// Others
|
||||
public static final String INVALID_CLIENT = "invalid_client";
|
||||
|
|
|
@ -63,6 +63,9 @@ public class OIDCLoginProtocol implements LoginProtocol {
|
|||
public static final String MAX_AGE_PARAM = OAuth2Constants.MAX_AGE;
|
||||
public static final String PROMPT_PARAM = OAuth2Constants.PROMPT;
|
||||
public static final String LOGIN_HINT_PARAM = "login_hint";
|
||||
public static final String REQUEST_PARAM = "request";
|
||||
public static final String REQUEST_URI_PARAM = "request_uri";
|
||||
|
||||
public static final String LOGOUT_REDIRECT_URI = "OIDC_LOGOUT_REDIRECT_URI";
|
||||
public static final String ISSUER = "iss";
|
||||
|
||||
|
|
|
@ -102,6 +102,9 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
|
|||
|
||||
config.setScopesSupported(SCOPES_SUPPORTED);
|
||||
|
||||
config.setRequestParameterSupported(false);
|
||||
config.setRequestUriParameterSupported(false);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
|
|||
|
||||
private Action action;
|
||||
private OIDCResponseType parsedResponseType;
|
||||
private OIDCResponseMode parsedResponseMode;
|
||||
|
||||
private String clientId;
|
||||
private String redirectUri;
|
||||
|
@ -162,6 +163,11 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
|
|||
logger.oidcScopeMissing();
|
||||
}
|
||||
|
||||
errorResponse = checkOIDCParams(params);
|
||||
if (errorResponse != null) {
|
||||
return errorResponse;
|
||||
}
|
||||
|
||||
createClientSession();
|
||||
// So back button doesn't work
|
||||
CacheControlUtil.noBackButtonCacheControlHeader();
|
||||
|
@ -313,6 +319,24 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
|
|||
return redirectErrorToClient(parsedResponseMode, OAuthErrorException.UNSUPPORTED_RESPONSE_TYPE, "Client is not allowed to initiate browser login with given response_type. Implicit flow is disabled for the client.");
|
||||
}
|
||||
|
||||
this.parsedResponseMode = parsedResponseMode;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Response checkOIDCParams(MultivaluedMap<String, String> params) {
|
||||
if (params.getFirst(OIDCLoginProtocol.REQUEST_PARAM) != null) {
|
||||
logger.unsupportedParameter(OIDCLoginProtocol.REQUEST_PARAM);
|
||||
event.error(Errors.INVALID_REQUEST);
|
||||
return redirectErrorToClient(parsedResponseMode, OAuthErrorException.REQUEST_NOT_SUPPORTED, null);
|
||||
}
|
||||
|
||||
if (params.getFirst(OIDCLoginProtocol.REQUEST_URI_PARAM) != null) {
|
||||
logger.unsupportedParameter(OIDCLoginProtocol.REQUEST_URI_PARAM);
|
||||
event.error(Errors.INVALID_REQUEST);
|
||||
return redirectErrorToClient(parsedResponseMode, OAuthErrorException.REQUEST_URI_NOT_SUPPORTED, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,12 @@ public class OIDCConfigurationRepresentation {
|
|||
@JsonProperty("scopes_supported")
|
||||
private List<String> scopesSupported;
|
||||
|
||||
@JsonProperty("request_parameter_supported")
|
||||
private Boolean requestParameterSupported;
|
||||
|
||||
@JsonProperty("request_uri_parameter_supported")
|
||||
private Boolean requestUriParameterSupported;
|
||||
|
||||
protected Map<String, Object> otherClaims = new HashMap<String, Object>();
|
||||
|
||||
public String getIssuer() {
|
||||
|
@ -242,6 +248,22 @@ public class OIDCConfigurationRepresentation {
|
|||
this.scopesSupported = scopesSupported;
|
||||
}
|
||||
|
||||
public Boolean getRequestParameterSupported() {
|
||||
return requestParameterSupported;
|
||||
}
|
||||
|
||||
public void setRequestParameterSupported(Boolean requestParameterSupported) {
|
||||
this.requestParameterSupported = requestParameterSupported;
|
||||
}
|
||||
|
||||
public Boolean getRequestUriParameterSupported() {
|
||||
return requestUriParameterSupported;
|
||||
}
|
||||
|
||||
public void setRequestUriParameterSupported(Boolean requestUriParameterSupported) {
|
||||
this.requestUriParameterSupported = requestUriParameterSupported;
|
||||
}
|
||||
|
||||
@JsonAnyGetter
|
||||
public Map<String, Object> getOtherClaims() {
|
||||
return otherClaims;
|
||||
|
|
|
@ -419,6 +419,10 @@ public interface ServicesLogger extends BasicLogger {
|
|||
void invalidParameter(String paramName);
|
||||
|
||||
@LogMessage(level = ERROR)
|
||||
@Message(id=94, value="Client is not allowed to initiate browser login with given response_type. %s flow is disabled for the client.")
|
||||
@Message(id=94, value="Unsupported parameter: %s")
|
||||
void unsupportedParameter(String paramName);
|
||||
|
||||
@LogMessage(level = ERROR)
|
||||
@Message(id=95, value="Client is not allowed to initiate browser login with given response_type. %s flow is disabled for the client.")
|
||||
void flowNotAllowed(String flowName);
|
||||
}
|
||||
|
|
|
@ -289,6 +289,78 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
|
|||
}
|
||||
|
||||
|
||||
// prompt=consent
|
||||
// NONCE
|
||||
|
||||
@Test
|
||||
public void nonceNotUsed() {
|
||||
driver.navigate().to(oauth.getLoginFormUrl());
|
||||
|
||||
loginPage.assertCurrent();
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||
|
||||
EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
|
||||
IDToken idToken = sendTokenRequestAndGetIDToken(loginEvent);
|
||||
|
||||
Assert.assertNull(idToken.getNonce());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonceMatches() {
|
||||
driver.navigate().to(oauth.getLoginFormUrl() + "&nonce=abcdef123456");
|
||||
|
||||
loginPage.assertCurrent();
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||
|
||||
EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
|
||||
IDToken idToken = sendTokenRequestAndGetIDToken(loginEvent);
|
||||
|
||||
Assert.assertEquals("abcdef123456", idToken.getNonce());
|
||||
}
|
||||
|
||||
// DISPLAY & OTHERS
|
||||
|
||||
@Test
|
||||
public void nonSupportedParams() {
|
||||
driver.navigate().to(oauth.getLoginFormUrl() + "&display=popup&foo=foobar");
|
||||
|
||||
loginPage.assertCurrent();
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||
|
||||
EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
|
||||
IDToken idToken = sendTokenRequestAndGetIDToken(loginEvent);
|
||||
|
||||
Assert.assertNotNull(idToken);
|
||||
}
|
||||
|
||||
// REQUEST & REQUEST_URI
|
||||
|
||||
@Test
|
||||
public void requestParam() {
|
||||
driver.navigate().to(oauth.getLoginFormUrl() + "&request=abc");
|
||||
|
||||
assertFalse(loginPage.isCurrent());
|
||||
assertTrue(appPage.isCurrent());
|
||||
|
||||
// Assert error response was sent because not logged in
|
||||
OAuthClient.AuthorizationCodeResponse resp = new OAuthClient.AuthorizationCodeResponse(oauth);
|
||||
Assert.assertNull(resp.getCode());
|
||||
Assert.assertEquals(OAuthErrorException.REQUEST_NOT_SUPPORTED, resp.getError());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriParam() {
|
||||
driver.navigate().to(oauth.getLoginFormUrl() + "&request_uri=https%3A%2F%2Flocalhost%3A60784%2Fexport%2FqzHTG11W48.jwt");
|
||||
|
||||
assertFalse(loginPage.isCurrent());
|
||||
assertTrue(appPage.isCurrent());
|
||||
|
||||
// Assert error response was sent because not logged in
|
||||
OAuthClient.AuthorizationCodeResponse resp = new OAuthClient.AuthorizationCodeResponse(oauth);
|
||||
Assert.assertNull(resp.getCode());
|
||||
Assert.assertEquals(OAuthErrorException.REQUEST_URI_NOT_SUPPORTED, resp.getError());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -98,6 +98,10 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
|
|||
|
||||
// Scopes supported
|
||||
Assert.assertNames(oidcConfig.getScopesSupported(), OAuth2Constants.SCOPE_OPENID, OAuth2Constants.OFFLINE_ACCESS);
|
||||
|
||||
// Request and Request_Uri
|
||||
Assert.assertFalse(oidcConfig.getRequestParameterSupported());
|
||||
Assert.assertFalse(oidcConfig.getRequestUriParameterSupported());
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue