set request object mandatory for client, restrict delivery mode

handle new attribute in client representation


add to UI
This commit is contained in:
Áron Bustya 2018-03-18 17:01:16 +01:00 committed by Marek Posolda
parent 917ba90f2c
commit 57f57f5c75
10 changed files with 383 additions and 0 deletions

View file

@ -86,6 +86,8 @@ public class OIDCClientRepresentation {
private String request_object_encryption_enc; private String request_object_encryption_enc;
private String request_object_required;
private Integer default_max_age; private Integer default_max_age;
private Boolean require_auth_time; private Boolean require_auth_time;
@ -337,6 +339,14 @@ public class OIDCClientRepresentation {
this.request_object_encryption_enc = request_object_encryption_enc; this.request_object_encryption_enc = request_object_encryption_enc;
} }
public String getRequestObjectRequired() {
return request_object_required;
}
public void setRequestObjectRequired(String request_object_required) {
this.request_object_required = request_object_required;
}
public Integer getDefaultMaxAge() { public Integer getDefaultMaxAge() {
return default_max_age; return default_max_age;
} }

View file

@ -32,6 +32,8 @@ public class OIDCAdvancedConfigWrapper {
private static final String REQUEST_OBJECT_SIGNATURE_ALG = "request.object.signature.alg"; private static final String REQUEST_OBJECT_SIGNATURE_ALG = "request.object.signature.alg";
private static final String REQUEST_OBJECT_REQUIRED = "request.object.required";
private static final String JWKS_URL = "jwks.url"; private static final String JWKS_URL = "jwks.url";
private static final String USE_JWKS_URL = "use.jwks.url"; private static final String USE_JWKS_URL = "use.jwks.url";
@ -80,6 +82,14 @@ public class OIDCAdvancedConfigWrapper {
setAttribute(REQUEST_OBJECT_SIGNATURE_ALG, algStr); setAttribute(REQUEST_OBJECT_SIGNATURE_ALG, algStr);
} }
public String getRequestObjectRequired() {
return getAttribute(REQUEST_OBJECT_REQUIRED);
}
public void setRequestObjectRequired(String requestObjectRequired) {
setAttribute(REQUEST_OBJECT_REQUIRED, requestObjectRequired);
}
public boolean isUseJwksUrl() { public boolean isUseJwksUrl() {
String useJwksUrl = getAttribute(USE_JWKS_URL); String useJwksUrl = getAttribute(USE_JWKS_URL);
return Boolean.parseBoolean(useJwksUrl); return Boolean.parseBoolean(useJwksUrl);

View file

@ -93,6 +93,11 @@ public class OIDCLoginProtocol implements LoginProtocol {
public static final String CLIENT_SECRET_JWT = "client_secret_jwt"; public static final String CLIENT_SECRET_JWT = "client_secret_jwt";
public static final String PRIVATE_KEY_JWT = "private_key_jwt"; public static final String PRIVATE_KEY_JWT = "private_key_jwt";
// Request object requirement options
public static final String REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI = "request or request_uri";
public static final String REQUEST_OBJECT_REQUIRED_REQUEST = "request only";
public static final String REQUEST_OBJECT_REQUIRED_REQUEST_URI = "request_uri only";
// https://tools.ietf.org/html/rfc7636#section-4.3 // https://tools.ietf.org/html/rfc7636#section-4.3
public static final String CODE_CHALLENGE_PARAM = "code_challenge"; public static final String CODE_CHALLENGE_PARAM = "code_challenge";
public static final String CODE_CHALLENGE_METHOD_PARAM = "code_challenge_method"; public static final String CODE_CHALLENGE_METHOD_PARAM = "code_challenge_method";

View file

@ -23,6 +23,7 @@ import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder; import org.keycloak.events.EventBuilder;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.services.ErrorPageException; import org.keycloak.services.ErrorPageException;
import org.keycloak.services.ServicesLogger; import org.keycloak.services.ServicesLogger;
@ -31,6 +32,9 @@ import org.keycloak.services.messages.Messages;
import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.io.InputStream; import java.io.InputStream;
import static org.keycloak.protocol.oidc.OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI;
import static org.keycloak.protocol.oidc.OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST;
import static org.keycloak.protocol.oidc.OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST_URI;
/** /**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -50,6 +54,19 @@ public class AuthorizationEndpointRequestParserProcessor {
throw new RuntimeException("Illegal to use both 'request' and 'request_uri' parameters together"); throw new RuntimeException("Illegal to use both 'request' and 'request_uri' parameters together");
} }
String requestObjectRequired = OIDCAdvancedConfigWrapper.fromClientModel(client).getRequestObjectRequired();
if (REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI.equals(requestObjectRequired)
&& requestParam == null && requestUriParam == null) {
throw new RuntimeException("Client is required to use 'request' or 'request_uri' parameter.");
} else if (REQUEST_OBJECT_REQUIRED_REQUEST.equals(requestObjectRequired)
&& requestParam == null) {
throw new RuntimeException("Client is required to use 'request' parameter.");
} else if (REQUEST_OBJECT_REQUIRED_REQUEST_URI.equals(requestObjectRequired)
&& requestUriParam == null) {
throw new RuntimeException("Client is required to use 'request_uri' parameter.");
}
if (requestParam != null) { if (requestParam != null) {
new AuthzEndpointRequestObjectParser(session, requestParam, client).parseRequest(request); new AuthzEndpointRequestObjectParser(session, requestParam, client).parseRequest(request);
} else if (requestUriParam != null) { } else if (requestUriParam != null) {

View file

@ -48,6 +48,7 @@ import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -115,6 +116,17 @@ public class DescriptionConverter {
configWrapper.setRequestObjectSignatureAlg(algorithm); configWrapper.setRequestObjectSignatureAlg(algorithm);
} }
if (clientOIDC.getRequestObjectRequired() != null) {
String requestObjectRequired = clientOIDC.getRequestObjectRequired();
if (Arrays.asList(
OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI,
OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST,
OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST_URI)
.contains(requestObjectRequired)) {
configWrapper.setRequestObjectRequired(requestObjectRequired);
}
}
return client; return client;
} }
@ -185,6 +197,9 @@ public class DescriptionConverter {
if (config.getRequestObjectSignatureAlg() != null) { if (config.getRequestObjectSignatureAlg() != null) {
response.setRequestObjectSigningAlg(config.getRequestObjectSignatureAlg().toString()); response.setRequestObjectSigningAlg(config.getRequestObjectSignatureAlg().toString());
} }
if (config.getRequestObjectRequired() != null) {
response.setRequestObjectRequired(config.getRequestObjectRequired());
}
if (config.isUseJwksUrl()) { if (config.isUseJwksUrl()) {
response.setJwksUri(config.getJwksUrl()); response.setJwksUri(config.getJwksUrl());
} }

View file

@ -201,6 +201,20 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
Assert.assertEquals(config.getRequestObjectSignatureAlg(), Algorithm.RS256); Assert.assertEquals(config.getRequestObjectSignatureAlg(), Algorithm.RS256);
} }
@Test
public void testRequestObjectRequired() throws Exception {
OIDCClientRepresentation clientRep = createRep();
clientRep.setRequestObjectRequired(OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI);
OIDCClientRepresentation response = reg.oidc().create(clientRep);
Assert.assertEquals(OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI, response.getRequestObjectRequired());
// Test Keycloak representation
ClientRepresentation kcClient = getClient(response.getClientId());
OIDCAdvancedConfigWrapper config = OIDCAdvancedConfigWrapper.fromClientRepresentation(kcClient);
Assert.assertEquals(OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI, config.getRequestObjectRequired());
}
@Test @Test
public void createClientImplicitFlow() throws ClientRegistrationException { public void createClientImplicitFlow() throws ClientRegistrationException {
OIDCClientRepresentation clientRep = createRep(); OIDCClientRepresentation clientRep = createRep();

View file

@ -71,6 +71,10 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.keycloak.protocol.oidc.OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI;
import static org.keycloak.protocol.oidc.OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST;
import static org.keycloak.protocol.oidc.OIDCLoginProtocol.REQUEST_OBJECT_REQUIRED_REQUEST_URI;
/** /**
* Test for supporting advanced parameters of OIDC specs (max_age, prompt, ...) * Test for supporting advanced parameters of OIDC specs (max_age, prompt, ...)
* *
@ -377,6 +381,281 @@ public class OIDCAdvancedRequestParamsTest extends AbstractTestRealmKeycloakTest
// REQUEST & REQUEST_URI // REQUEST & REQUEST_URI
@Test
public void requestObjectNotRequiredNotProvided() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
// Send request without request object
// Assert that the request is accepted
OAuthClient.AuthorizationEndpointResponse response = oauth.doLogin("test-user@localhost", "password");
Assert.assertNotNull(response.getCode());
Assert.assertEquals("mystate2", response.getState());
assertTrue(appPage.isCurrent());
}
@Test
public void requestObjectNotRequiredProvidedInRequestParam() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
// Set up a request object
TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
oidcClientEndpointsResource.setOIDCRequest("test", "test-app", oauth.getRedirectUri(), "10", Algorithm.none.toString());
// Send request object in "request" param
oauth.request(oidcClientEndpointsResource.getOIDCRequest());
// Assert that the request is accepted
OAuthClient.AuthorizationEndpointResponse response1 = oauth.doLogin("test-user@localhost", "password");
Assert.assertNotNull(response1.getCode());
Assert.assertEquals("mystate2", response1.getState());
assertTrue(appPage.isCurrent());
}
@Test
public void requestObjectNotRequiredProvidedInRequestUriParam() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
// Set up a request object
TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
oidcClientEndpointsResource.setOIDCRequest("test", "test-app", oauth.getRedirectUri(), "10", Algorithm.none.toString());
// Send request object reference in "request_uri" param
oauth.requestUri(TestApplicationResourceUrls.clientRequestUri());
// Assert that the request is accepted
OAuthClient.AuthorizationEndpointResponse response2 = oauth.doLogin("test-user@localhost", "password");
Assert.assertNotNull(response2.getCode());
Assert.assertEquals("mystate2", response2.getState());
assertTrue(appPage.isCurrent());
}
@Test
public void requestObjectRequiredNotProvided() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI);
clientResource.update(clientRep);
// Send request without request object
// Assert that the request is not accepted
oauth.openLoginForm();
Assert.assertTrue(errorPage.isCurrent());
assertEquals("Invalid Request", errorPage.getError());
// Revert requiring request object for client
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
}
@Test
public void requestObjectRequiredProvidedInRequestParam() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI);
clientResource.update(clientRep);
// Set up a request object
TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
oidcClientEndpointsResource.setOIDCRequest("test", "test-app", oauth.getRedirectUri(), "10", Algorithm.none.toString());
// Send request object in "request" param
oauth.request(oidcClientEndpointsResource.getOIDCRequest());
// Assert that the request is accepted
OAuthClient.AuthorizationEndpointResponse response1 = oauth.doLogin("test-user@localhost", "password");
Assert.assertNotNull(response1.getCode());
Assert.assertEquals("mystate2", response1.getState());
assertTrue(appPage.isCurrent());
// Revert requiring request object for client
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
}
@Test
public void requestObjectRequiredProvidedInRequestUriParam() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI);
clientResource.update(clientRep);
// Set up a request object
TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
oidcClientEndpointsResource.setOIDCRequest("test", "test-app", oauth.getRedirectUri(), "10", Algorithm.none.toString());
// Send request object reference in "request_uri" param
oauth.requestUri(TestApplicationResourceUrls.clientRequestUri());
// Assert that the request is accepted
OAuthClient.AuthorizationEndpointResponse response2 = oauth.doLogin("test-user@localhost", "password");
Assert.assertNotNull(response2.getCode());
Assert.assertEquals("mystate2", response2.getState());
assertTrue(appPage.isCurrent());
// Revert requiring request object for client
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
}
@Test
public void requestObjectRequiredAsRequestParamNotProvided() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(REQUEST_OBJECT_REQUIRED_REQUEST);
clientResource.update(clientRep);
// Send request without request object
// Assert that the request is not accepted
oauth.openLoginForm();
Assert.assertTrue(errorPage.isCurrent());
assertEquals("Invalid Request", errorPage.getError());
// Revert requiring request object for client
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
}
@Test
public void requestObjectRequiredAsRequestParamProvidedInRequestParam() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(REQUEST_OBJECT_REQUIRED_REQUEST);
clientResource.update(clientRep);
// Set up a request object
TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
oidcClientEndpointsResource.setOIDCRequest("test", "test-app", oauth.getRedirectUri(), "10", Algorithm.none.toString());
// Send request object in "request" param
oauth.request(oidcClientEndpointsResource.getOIDCRequest());
// Assert that the request is accepted
OAuthClient.AuthorizationEndpointResponse response1 = oauth.doLogin("test-user@localhost", "password");
Assert.assertNotNull(response1.getCode());
Assert.assertEquals("mystate2", response1.getState());
assertTrue(appPage.isCurrent());
// Revert requiring request object for client
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
}
@Test
public void requestObjectRequiredAsRequestParamProvidedInRequestUriParam() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(REQUEST_OBJECT_REQUIRED_REQUEST);
clientResource.update(clientRep);
// Set up a request object
TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
oidcClientEndpointsResource.setOIDCRequest("test", "test-app", oauth.getRedirectUri(), "10", Algorithm.none.toString());
// Send request object reference in "request_uri" param
oauth.requestUri(TestApplicationResourceUrls.clientRequestUri());
// Assert that the request is accepted
oauth.openLoginForm();
Assert.assertTrue(errorPage.isCurrent());
assertEquals("Invalid Request", errorPage.getError());
// Revert requiring request object for client
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
}
@Test
public void requestObjectRequiredAsRequestUriParamNotProvided() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(REQUEST_OBJECT_REQUIRED_REQUEST_URI);
clientResource.update(clientRep);
// Send request without request object
// Assert that the request is not accepted
oauth.openLoginForm();
Assert.assertTrue(errorPage.isCurrent());
assertEquals("Invalid Request", errorPage.getError());
// Revert requiring request object for client
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
}
@Test
public void requestObjectRequiredAsRequestUriParamProvidedInRequestParam() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(REQUEST_OBJECT_REQUIRED_REQUEST_URI);
clientResource.update(clientRep);
// Set up a request object
TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
oidcClientEndpointsResource.setOIDCRequest("test", "test-app", oauth.getRedirectUri(), "10", Algorithm.none.toString());
// Send request object in "request" param
oauth.request(oidcClientEndpointsResource.getOIDCRequest());
// Assert that the request is not accepted
oauth.openLoginForm();
Assert.assertTrue(errorPage.isCurrent());
assertEquals("Invalid Request", errorPage.getError());
// Revert requiring request object for client
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
}
@Test
public void requestObjectRequiredAsRequestUriParamProvidedInRequestUriParam() throws Exception {
oauth.stateParamHardcoded("mystate2");
// Set request object not required for client
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(REQUEST_OBJECT_REQUIRED_REQUEST_URI);
clientResource.update(clientRep);
// Set up a request object
TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
oidcClientEndpointsResource.setOIDCRequest("test", "test-app", oauth.getRedirectUri(), "10", Algorithm.none.toString());
// Send request object reference in "request_uri" param
oauth.requestUri(TestApplicationResourceUrls.clientRequestUri());
// Assert that the request is accepted
OAuthClient.AuthorizationEndpointResponse response1 = oauth.doLogin("test-user@localhost", "password");
Assert.assertNotNull(response1.getCode());
Assert.assertEquals("mystate2", response1.getState());
assertTrue(appPage.isCurrent());
// Revert requiring request object for client
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectRequired(null);
clientResource.update(clientRep);
}
@Test @Test
public void requestParamUnsigned() throws Exception { public void requestParamUnsigned() throws Exception {
oauth.stateParamHardcoded("mystate2"); oauth.stateParamHardcoded("mystate2");

View file

@ -309,6 +309,8 @@ user-info-signed-response-alg=User Info Signed Response Algorithm
user-info-signed-response-alg.tooltip=JWA algorithm used for signed User Info Endpoint response. If set to 'unsigned', then User Info Response won't be signed and will be returned in application/json format. user-info-signed-response-alg.tooltip=JWA algorithm used for signed User Info Endpoint response. If set to 'unsigned', then User Info Response won't be signed and will be returned in application/json format.
request-object-signature-alg=Request Object Signature Algorithm request-object-signature-alg=Request Object Signature Algorithm
request-object-signature-alg.tooltip=JWA algorithm, which client needs to use when sending OIDC request object specified by 'request' or 'request_uri' parameters. If set to 'any', then Request object can be signed by any algorithm (including 'none' ). request-object-signature-alg.tooltip=JWA algorithm, which client needs to use when sending OIDC request object specified by 'request' or 'request_uri' parameters. If set to 'any', then Request object can be signed by any algorithm (including 'none' ).
request-object-required=Request Object Required
request-object-required-alg.tooltip=Specifies if the client needs to provide a request object with their authorization requests, and what method they can use for this. If set to "not required", providing a request object is optional. In all other cases providing a request object is mandatory. If set to "request", the request object must be provided by value. If set to "request_uri", the request object must be provided by reference. If set to "request or request_uri", either method can be used.
fine-saml-endpoint-conf=Fine Grain SAML Endpoint Configuration fine-saml-endpoint-conf=Fine Grain SAML Endpoint Configuration
fine-saml-endpoint-conf.tooltip=Expand this section to configure exact URLs for Assertion Consumer and Single Logout Service. fine-saml-endpoint-conf.tooltip=Expand this section to configure exact URLs for Assertion Consumer and Single Logout Service.
assertion-consumer-post-binding-url=Assertion Consumer Service POST Binding URL assertion-consumer-post-binding-url=Assertion Consumer Service POST Binding URL

View file

@ -892,6 +892,13 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, templates,
"RS256" "RS256"
]; ];
$scope.requestObjectRequiredOptions = [
"not required",
"request or request_uri",
"request only",
"request_uri only"
];
$scope.realm = realm; $scope.realm = realm;
$scope.samlAuthnStatement = false; $scope.samlAuthnStatement = false;
$scope.samlOneTimeUseCondition = false; $scope.samlOneTimeUseCondition = false;
@ -1045,6 +1052,9 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, templates,
var attrVal2 = $scope.client.attributes['request.object.signature.alg']; var attrVal2 = $scope.client.attributes['request.object.signature.alg'];
$scope.requestObjectSignatureAlg = attrVal2==null ? 'any' : attrVal2; $scope.requestObjectSignatureAlg = attrVal2==null ? 'any' : attrVal2;
var attrVal3 = $scope.client.attributes['request.object.required'];
$scope.requestObjectRequired = attrVal3==null ? 'not required' : attrVal3;
if ($scope.client.attributes["exclude.session.state.from.auth.response"]) { if ($scope.client.attributes["exclude.session.state.from.auth.response"]) {
if ($scope.client.attributes["exclude.session.state.from.auth.response"] == "true") { if ($scope.client.attributes["exclude.session.state.from.auth.response"] == "true") {
$scope.excludeSessionStateFromAuthResponse = true; $scope.excludeSessionStateFromAuthResponse = true;
@ -1144,6 +1154,14 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, templates,
} }
}; };
$scope.changeRequestObjectRequired = function() {
if ($scope.requestObjectRequired === 'not required') {
$scope.clientEdit.attributes['request.object.required'] = null;
} else {
$scope.clientEdit.attributes['request.object.required'] = $scope.requestObjectRequired;
}
};
$scope.$watch(function() { $scope.$watch(function() {
return $location.path(); return $location.path();
}, function() { }, function() {

View file

@ -409,6 +409,19 @@
</div> </div>
<kc-tooltip>{{:: 'request-object-signature-alg.tooltip' | translate}}</kc-tooltip> <kc-tooltip>{{:: 'request-object-signature-alg.tooltip' | translate}}</kc-tooltip>
</div> </div>
<div class="form-group clearfix block" data-ng-show="protocol == 'openid-connect'">
<label class="col-md-2 control-label" for="changeRequestObjectRequired">{{:: 'request-object-required' | translate}}</label>
<div class="col-sm-6">
<div>
<select class="form-control" id="requestObjectRequired"
ng-change="changeRequestObjectRequired()"
ng-model="requestObjectRequired"
ng-options="sig for sig in requestObjectRequiredOptions">
</select>
</div>
</div>
<kc-tooltip>{{:: 'request-object-required.tooltip' | translate}}</kc-tooltip>
</div>
</fieldset> </fieldset>
<fieldset data-ng-show="protocol == 'openid-connect'"> <fieldset data-ng-show="protocol == 'openid-connect'">