KEYCLOAK-3354 request and request_uri not supported

This commit is contained in:
mposolda 2016-07-22 13:22:55 +02:00
parent 94af2e1789
commit 9169bcd88d
8 changed files with 137 additions and 3 deletions

View file

@ -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";

View file

@ -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";

View file

@ -102,6 +102,9 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
config.setScopesSupported(SCOPES_SUPPORTED);
config.setRequestParameterSupported(false);
config.setRequestUriParameterSupported(false);
return config;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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());
}
}

View file

@ -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();
}