enforce clients using a redirect flow have at least one redirect uri registered when using dynamic registration, made error handling more consistent across all APIs
closes #596pull/604/head
parent
c38761cc23
commit
4e890a4d7d
|
@ -98,7 +98,8 @@ var ListWidgetChildView = Backbone.View.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
@ -351,7 +352,8 @@ var BlackListWidgetView = ListWidgetView.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
|
|
@ -245,7 +245,8 @@ var ClientView = Backbone.View.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
@ -772,7 +773,8 @@ var ClientFormView = Backbone.View.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
|
|
@ -178,7 +178,8 @@ var DynRegEditView = Backbone.View.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
@ -343,7 +344,8 @@ var DynRegEditView = Backbone.View.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
|
|
@ -250,7 +250,8 @@ var ApprovedSiteView = Backbone.View.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
|
|
@ -111,7 +111,8 @@ var SystemScopeView = Backbone.View.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
@ -295,27 +296,15 @@ var SystemScopeFormView = Backbone.View.extend({
|
||||||
//Pull out the response text.
|
//Pull out the response text.
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
if (response.status == 409) {
|
//Display an alert with an error message
|
||||||
//Conflict, scope already exists
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
$('#value.control-group input').addClass('inputError');
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
$('#value.control-group').before('<div class="alert alert-error"><button type="button" class="close" data-dismiss="alert">×</button>' + responseText + '</div>');
|
|
||||||
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
$('#value.control-group').bind('click.error', function() {
|
"backdrop" : "static",
|
||||||
$('#value.control-group input').removeClass('inputError');
|
"keyboard" : true,
|
||||||
$('#value.control-group').unbind('click.error');
|
"show" : true // ensure the modal is shown immediately
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//Display an alert with an error message
|
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
|
||||||
"backdrop" : "static",
|
|
||||||
"keyboard" : true,
|
|
||||||
"show" : true // ensure the modal is shown immediately
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,8 @@ var AccessTokenView = Backbone.View.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
@ -268,7 +269,8 @@ var RefreshTokenView = Backbone.View.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
|
|
@ -194,7 +194,8 @@ var WhiteListView = Backbone.View.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
@ -278,7 +279,8 @@ var WhiteListFormView = Backbone.View.extend({
|
||||||
var responseJson = JSON.parse(response.responseText);
|
var responseJson = JSON.parse(response.responseText);
|
||||||
|
|
||||||
//Display an alert with an error message
|
//Display an alert with an error message
|
||||||
$('#modalAlert div.modal-body').html(responseJson.errorMessage);
|
$('#modalAlert div.modal-header').html(responseJson.error);
|
||||||
|
$('#modalAlert div.modal-body').html(responseJson.error_description);
|
||||||
|
|
||||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||||
"backdrop" : "static",
|
"backdrop" : "static",
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.springframework.stereotype.Component;
|
||||||
import org.springframework.validation.BeanPropertyBindingResult;
|
import org.springframework.validation.BeanPropertyBindingResult;
|
||||||
import org.springframework.web.servlet.view.AbstractView;
|
import org.springframework.web.servlet.view.AbstractView;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.google.gson.ExclusionStrategy;
|
import com.google.gson.ExclusionStrategy;
|
||||||
import com.google.gson.FieldAttributes;
|
import com.google.gson.FieldAttributes;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
@ -85,9 +86,14 @@ public class JsonErrorView extends AbstractView {
|
||||||
|
|
||||||
Writer out = response.getWriter();
|
Writer out = response.getWriter();
|
||||||
|
|
||||||
|
String errorTitle = (String) model.get("error");
|
||||||
|
if (Strings.isNullOrEmpty(errorTitle)) {
|
||||||
|
errorTitle = "Error";
|
||||||
|
}
|
||||||
String errorMessage = (String) model.get("errorMessage");
|
String errorMessage = (String) model.get("errorMessage");
|
||||||
JsonObject obj = new JsonObject();
|
JsonObject obj = new JsonObject();
|
||||||
obj.addProperty("error_message", errorMessage);
|
obj.addProperty("error", errorTitle);
|
||||||
|
obj.addProperty("error_description", errorMessage);
|
||||||
gson.toJson(obj, out);
|
gson.toJson(obj, out);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.mitre.openid.connect.web;
|
package org.mitre.openid.connect.web;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ import org.mitre.oauth2.service.OAuth2TokenEntityService;
|
||||||
import org.mitre.oauth2.service.SystemScopeService;
|
import org.mitre.oauth2.service.SystemScopeService;
|
||||||
import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor;
|
import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor;
|
||||||
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
||||||
|
import org.mitre.openid.connect.service.BlacklistedSiteService;
|
||||||
import org.mitre.openid.connect.service.OIDCTokenService;
|
import org.mitre.openid.connect.service.OIDCTokenService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -47,6 +49,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.util.UriUtils;
|
import org.springframework.web.util.UriUtils;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
|
@ -64,6 +67,9 @@ public class ClientDynamicRegistrationEndpoint {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SystemScopeService scopeService;
|
private SystemScopeService scopeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BlacklistedSiteService blacklistService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ConfigurationPropertiesBean config;
|
private ConfigurationPropertiesBean config;
|
||||||
|
@ -121,10 +127,33 @@ public class ClientDynamicRegistrationEndpoint {
|
||||||
newClient.setGrantTypes(Sets.newHashSet("authorization_code")); // allow authorization code grant type by default
|
newClient.setGrantTypes(Sets.newHashSet("authorization_code")); // allow authorization code grant type by default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check to make sure this client registered a redirect URI if using a redirect flow
|
||||||
|
if (newClient.getGrantTypes().contains("authorization_code") || newClient.getGrantTypes().contains("implicit")) {
|
||||||
|
if (newClient.getRedirectUris() == null || newClient.getRedirectUris().isEmpty()) {
|
||||||
|
// return an error
|
||||||
|
m.addAttribute("error", "invalid_client_uri");
|
||||||
|
m.addAttribute("errorMessage", "Clients using a redirect-based grant type must register at least one redirect URI.");
|
||||||
|
m.addAttribute("code", HttpStatus.BAD_REQUEST);
|
||||||
|
return "jsonErrorView";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String uri : newClient.getRedirectUris()) {
|
||||||
|
if (blacklistService.isBlacklisted(uri)) {
|
||||||
|
// return an error
|
||||||
|
m.addAttribute("error", "invalid_client_uri");
|
||||||
|
m.addAttribute("errorMessage", "Redirect URI is not allowed: " + uri);
|
||||||
|
m.addAttribute("code", HttpStatus.BAD_REQUEST);
|
||||||
|
return "jsonErrorView";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// set default response types if needed
|
// set default response types if needed
|
||||||
// TODO: these aren't checked by SECOAUTH
|
// TODO: these aren't checked by SECOAUTH
|
||||||
// TODO: the consistency between the response_type and grant_type needs to be checked by the client service, most likely
|
// TODO: the consistency between the response_type and grant_type needs to be checked by the client service, most likely
|
||||||
|
|
||||||
if (newClient.getResponseTypes() == null || newClient.getResponseTypes().isEmpty()) {
|
if (newClient.getResponseTypes() == null || newClient.getResponseTypes().isEmpty()) {
|
||||||
newClient.setResponseTypes(Sets.newHashSet("code")); // default to allowing only the auth code flow
|
newClient.setResponseTypes(Sets.newHashSet("code")); // default to allowing only the auth code flow
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue