added in UI shell for creating/editing resources (clients with "introspection" set and no grants or other parameters)
parent
b8908b6efe
commit
0775785ce3
|
@ -15,4 +15,5 @@
|
|||
<li><a href="manage/#user/profile">View Profile Information</a></li>
|
||||
<li class="divider"></li>
|
||||
<li class="nav-header">Developer</li>
|
||||
<li><a href="manage/#dev/dynreg">Self-service client registration</a><li>
|
||||
<li><a href="manage/#dev/dynreg">Self-service client registration</a><li>
|
||||
<li><a href="manage/#dev/resource">Self-service protected resource registration</a><li>
|
|
@ -29,6 +29,7 @@
|
|||
<script type="text/javascript" src="resources/js/scope.js"></script>
|
||||
<script type="text/javascript" src="resources/js/whitelist.js"></script>
|
||||
<script type="text/javascript" src="resources/js/dynreg.js"></script>
|
||||
<script type="text/javascript" src="resources/js/rsreg.js"></script>
|
||||
<script type="text/javascript" src="resources/js/token.js"></script>
|
||||
<script type="text/javascript" src="resources/js/admin.js"></script>
|
||||
</c:if>
|
||||
|
|
|
@ -426,6 +426,10 @@ var AppRouter = Backbone.Router.extend({
|
|||
"dev/dynreg/new":"newDynReg",
|
||||
"dev/dynreg/edit":"editDynReg",
|
||||
|
||||
"dev/resource":"resReg",
|
||||
"dev/resource/new":"newResReg",
|
||||
"dev/resource/edit":"editResReg",
|
||||
|
||||
"": "root"
|
||||
|
||||
},
|
||||
|
@ -456,6 +460,7 @@ var AppRouter = Backbone.Router.extend({
|
|||
this.systemScopeListView = new SystemScopeListView({model:this.systemScopeList});
|
||||
this.tokensListView = new TokenListView({model: {access: this.accessTokensList, refresh: this.refreshTokensList}, clientList: this.clientList, systemScopeList: this.systemScopeList});
|
||||
this.dynRegRootView = new DynRegRootView({systemScopeList: this.systemScopeList});
|
||||
this.resRegRootView = new ResRegRootView({systemScopeList: this.systemScopeList});
|
||||
|
||||
this.breadCrumbView = new BreadCrumbView({
|
||||
collection:new Backbone.Collection()
|
||||
|
@ -893,13 +898,66 @@ var AppRouter = Backbone.Router.extend({
|
|||
this.breadCrumbView.collection.add([
|
||||
{text:"Home", href:""},
|
||||
{text:"Client Registration", href:"manage/#dev/dynreg"},
|
||||
{text:"Edit", href:"manage/#dev/dynreg/new"}
|
||||
{text:"Edit", href:"manage/#dev/dynreg/edit"}
|
||||
]);
|
||||
|
||||
setPageTitle("Edit a Dynamically Registered Client");
|
||||
// note that this doesn't actually load the client, that's supposed to happen elsewhere...
|
||||
},
|
||||
|
||||
resReg:function() {
|
||||
this.breadCrumbView.collection.reset();
|
||||
this.breadCrumbView.collection.add([
|
||||
{text:"Home", href:""},
|
||||
{text:"Protected Resource Registration", href:"manage/#dev/resource"}
|
||||
]);
|
||||
|
||||
this.resRegRootView.load(function() {
|
||||
$('#content').html(app.resRegRootView.render().el);
|
||||
|
||||
setPageTitle("Self-service Protected Resource Registration");
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
newResReg:function() {
|
||||
this.breadCrumbView.collection.reset();
|
||||
this.breadCrumbView.collection.add([
|
||||
{text:"Home", href:""},
|
||||
{text:"Protected Resource Registration", href:"manage/#dev/resource"},
|
||||
{text:"New", href:"manage/#dev/resource/new"}
|
||||
]);
|
||||
|
||||
var client = new ResRegClient();
|
||||
var view = new ResRegEditView({model: client, systemScopeList:this.systemScopeList});
|
||||
|
||||
view.load(function() {
|
||||
|
||||
client.set({
|
||||
scope: _.uniq(_.flatten(app.systemScopeList.defaultDynRegScopes().pluck("value"))).join(" "),
|
||||
token_endpoint_auth_method: 'client_secret_basic',
|
||||
}, { silent: true });
|
||||
|
||||
$('#content').html(view.render().el);
|
||||
view.delegateEvents();
|
||||
setPageTitle("Dynamically Register a New Protected Resource");
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
editResReg:function() {
|
||||
this.breadCrumbView.collection.reset();
|
||||
this.breadCrumbView.collection.add([
|
||||
{text:"Home", href:""},
|
||||
{text:"Protected Resource Registration", href:"manage/#dev/resource"},
|
||||
{text:"Edit", href:"manage/#dev/resource/edit"}
|
||||
]);
|
||||
|
||||
setPageTitle("Edit a Dynamically Registered Protected Resource");
|
||||
// note that this doesn't actually load the client, that's supposed to happen elsewhere...
|
||||
},
|
||||
|
||||
profile:function() {
|
||||
this.breadCrumbView.collection.reset();
|
||||
this.breadCrumbView.collection.add([
|
||||
|
@ -937,6 +995,7 @@ $(function () {
|
|||
$.get('resources/template/scope.html', _load);
|
||||
$.get('resources/template/whitelist.html', _load);
|
||||
$.get('resources/template/dynreg.html', _load);
|
||||
$.get('resources/template/rsreg.html', _load);
|
||||
$.get('resources/template/token.html', _load);
|
||||
|
||||
jQuery.ajaxSetup({async:true});
|
||||
|
|
|
@ -0,0 +1,458 @@
|
|||
var ResRegClient = Backbone.Model.extend({
|
||||
idAttribute: "client_id",
|
||||
|
||||
defaults:{
|
||||
client_id:null,
|
||||
client_secret:null,
|
||||
redirect_uris:[],
|
||||
client_name:null,
|
||||
client_uri:null,
|
||||
logo_uri:null,
|
||||
contacts:[],
|
||||
tos_uri:null,
|
||||
token_endpoint_auth_method:null,
|
||||
scope:null,
|
||||
grant_types:[],
|
||||
response_types:[],
|
||||
policy_uri:null,
|
||||
jwks_uri:null,
|
||||
|
||||
application_type:null,
|
||||
sector_identifier_uri:null,
|
||||
subject_type:null,
|
||||
|
||||
request_object_signing_alg:null,
|
||||
|
||||
userinfo_signed_response_alg:null,
|
||||
userinfo_encrypted_response_alg:null,
|
||||
userinfo_encrypted_response_enc:null,
|
||||
|
||||
id_token_signed_response_alg:null,
|
||||
id_token_encrypted_response_alg:null,
|
||||
id_token_encrypted_response_enc:null,
|
||||
|
||||
default_max_age:null,
|
||||
require_auth_time:false,
|
||||
default_acr_values:null,
|
||||
|
||||
initiate_login_uri:null,
|
||||
post_logout_redirect_uri:null,
|
||||
|
||||
request_uris:[],
|
||||
|
||||
client_description:null,
|
||||
|
||||
registration_access_token:null,
|
||||
registration_client_uri:null
|
||||
},
|
||||
|
||||
sync: function(method, model, options){
|
||||
if (model.get('registration_access_token')) {
|
||||
var headers = options.headers ? options.headers : {};
|
||||
headers['Authorization'] = 'Bearer ' + model.get('registration_access_token');
|
||||
options.headers = headers;
|
||||
}
|
||||
|
||||
return this.constructor.__super__.sync(method, model, options);
|
||||
},
|
||||
|
||||
urlRoot:'resource'
|
||||
|
||||
});
|
||||
|
||||
var ResRegRootView = Backbone.View.extend({
|
||||
|
||||
tagName: 'span',
|
||||
|
||||
initialize:function() {
|
||||
|
||||
},
|
||||
|
||||
events:{
|
||||
"click #newreg":"newReg",
|
||||
"click #editreg":"editReg"
|
||||
},
|
||||
|
||||
load:function(callback) {
|
||||
if (this.options.systemScopeList.isFetched) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
$('#loadingbox').sheet('show');
|
||||
$('#loading').html('<span class="label" id="loading-scopes">Scopes</span> ');
|
||||
|
||||
$.when(this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}}))
|
||||
.done(function() {
|
||||
$('#loadingbox').sheet('hide');
|
||||
callback();
|
||||
});
|
||||
},
|
||||
|
||||
render:function() {
|
||||
$(this.el).html($('#tmpl-rsreg').html());
|
||||
return this;
|
||||
},
|
||||
|
||||
newReg:function(e) {
|
||||
e.preventDefault();
|
||||
this.remove();
|
||||
app.navigate('dev/resource/new', {trigger: true});
|
||||
},
|
||||
|
||||
editReg:function(e) {
|
||||
e.preventDefault();
|
||||
var clientId = $('#clientId').val();
|
||||
var token = $('#regtoken').val();
|
||||
|
||||
var client = new DynRegClient({
|
||||
client_id: clientId,
|
||||
registration_access_token: token
|
||||
});
|
||||
|
||||
var self = this;
|
||||
|
||||
client.fetch({success: function() {
|
||||
|
||||
var view = new ResRegEditView({model: client, systemScopeList: app.systemScopeList});
|
||||
|
||||
view.load(function() {
|
||||
$('#content').html(view.render().el);
|
||||
view.delegateEvents();
|
||||
setPageTitle("Dynamically Register a New Protected Resource");
|
||||
app.navigate('dev/resource/edit', {trigger: true});
|
||||
self.remove();
|
||||
});
|
||||
}, error: function() {
|
||||
$('#modalAlert div.modal-body').html("Invalid resource or registration access token.");
|
||||
|
||||
$("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
|
||||
"backdrop" : "static",
|
||||
"keyboard" : true,
|
||||
"show" : true // ensure the modal is shown immediately
|
||||
});
|
||||
|
||||
}});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var ResRegEditView = Backbone.View.extend({
|
||||
|
||||
tagName: 'span',
|
||||
|
||||
initialize:function() {
|
||||
if (!this.template) {
|
||||
this.template = _.template($('#tmpl-rsreg-resource-form').html());
|
||||
}
|
||||
|
||||
this.redirectUrisCollection = new Backbone.Collection();
|
||||
this.scopeCollection = new Backbone.Collection();
|
||||
this.contactsCollection = new Backbone.Collection();
|
||||
this.defaultAcrValuesCollection = new Backbone.Collection();
|
||||
this.requestUrisCollection = new Backbone.Collection();
|
||||
},
|
||||
|
||||
load:function(callback) {
|
||||
if (this.options.systemScopeList.isFetched) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
$('#loadingbox').sheet('show');
|
||||
$('#loading').html('<span class="label" id="loading-scopes">Scopes</span> ');
|
||||
|
||||
$.when(this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}}))
|
||||
.done(function() {
|
||||
$('#loadingbox').sheet('hide');
|
||||
callback();
|
||||
});
|
||||
},
|
||||
|
||||
events:{
|
||||
"click .btn-save":"saveClient",
|
||||
"click .btn-cancel": function() { window.history.back(); return false; },
|
||||
"click .btn-delete":"deleteClient",
|
||||
"change #logoUri input":"previewLogo"
|
||||
},
|
||||
|
||||
deleteClient:function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (confirm("Are you sure sure you would like to delete this client?")) {
|
||||
var self = this;
|
||||
|
||||
this.model.destroy({
|
||||
success:function () {
|
||||
self.remove();
|
||||
app.navigate('dev/dynreg', {trigger: true});
|
||||
},
|
||||
error:function (error, response) {
|
||||
console.log("An error occurred when deleting a client");
|
||||
|
||||
//Pull out the response text.
|
||||
var responseJson = JSON.parse(response.responseText);
|
||||
|
||||
//Display an alert with an error message
|
||||
$('#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
|
||||
"backdrop" : "static",
|
||||
"keyboard" : true,
|
||||
"show" : true // ensure the modal is shown immediately
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
app.clientListView.delegateEvents();
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
previewLogo:function() {
|
||||
if ($('#logoUri input', this.el).val()) {
|
||||
$('#logoPreview', this.el).empty();
|
||||
$('#logoPreview', this.el).attr('src', $('#logoUri input').val());
|
||||
} else {
|
||||
$('#logoBlock', this.el).hide();
|
||||
}
|
||||
},
|
||||
|
||||
disableUnsupportedJOSEItems:function(serverSupported, query) {
|
||||
var supported = ['default'];
|
||||
if (serverSupported) {
|
||||
supported = _.union(supported, serverSupported);
|
||||
}
|
||||
$(query, this.$el).each(function(idx) {
|
||||
if(_.contains(supported, $(this).val())) {
|
||||
$(this).prop('disabled', false);
|
||||
} else {
|
||||
$(this).prop('disabled', true);
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
// returns "null" if given the value "default" as a string, otherwise returns input value. useful for parsing the JOSE algorithm dropdowns
|
||||
defaultToNull:function(value) {
|
||||
if (value == 'default') {
|
||||
return null;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
// maps from a form-friendly name to the real grant parameter name
|
||||
grantMap:{
|
||||
'authorization_code': 'authorization_code',
|
||||
'password': 'password',
|
||||
'implicit': 'implicit',
|
||||
'client_credentials': 'client_credentials',
|
||||
'redelegate': 'urn:ietf:params:oauth:grant_type:redelegate',
|
||||
'refresh_token': 'refresh_token'
|
||||
},
|
||||
|
||||
// maps from a form-friendly name to the real response type parameter name
|
||||
responseMap:{
|
||||
'code': 'code',
|
||||
'token': 'token',
|
||||
'idtoken': 'id_token',
|
||||
'token-idtoken': 'token id_token',
|
||||
'code-idtoken': 'code id_token',
|
||||
'code-token': 'code token',
|
||||
'code-token-idtoken': 'code token id_token'
|
||||
},
|
||||
|
||||
saveClient:function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
$('.control-group').removeClass('error');
|
||||
|
||||
// build the scope object
|
||||
var scopes = this.scopeCollection.pluck("item").join(" ");
|
||||
|
||||
// build the grant type object
|
||||
var grantTypes = [];
|
||||
$.each(this.grantMap, function(index,type) {
|
||||
if ($('#grantTypes-' + index).is(':checked')) {
|
||||
grantTypes.push(type);
|
||||
}
|
||||
});
|
||||
|
||||
// build the response type object
|
||||
var responseTypes = [];
|
||||
$.each(this.responseMap, function(index,type) {
|
||||
if ($('#responseTypes-' + index).is(':checked')) {
|
||||
responseTypes.push(type);
|
||||
}
|
||||
});
|
||||
|
||||
var contacts = this.contactsCollection.pluck('item');
|
||||
var userInfo = getUserInfo();
|
||||
if (userInfo && userInfo.email) {
|
||||
if (!_.contains(contacts, userInfo.email)) {
|
||||
contacts.push(userInfo.email);
|
||||
}
|
||||
}
|
||||
|
||||
var attrs = {
|
||||
client_name:$('#clientName input').val(),
|
||||
redirect_uris: this.redirectUrisCollection.pluck("item"),
|
||||
client_description:$('#clientDescription textarea').val(),
|
||||
logo_uri:$('#logoUri input').val(),
|
||||
grant_types: grantTypes,
|
||||
scope: scopes,
|
||||
|
||||
tos_uri: $('#tosUri input').val(),
|
||||
policy_uri: $('#policyUri input').val(),
|
||||
client_uri: $('#clientUri input').val(),
|
||||
application_type: $('#applicationType input').filter(':checked').val(),
|
||||
jwks_uri: $('#jwksUri input').val(),
|
||||
subject_type: $('#subjectType input').filter(':checked').val(),
|
||||
token_endpoint_auth_method: $('#tokenEndpointAuthMethod input').filter(':checked').val(),
|
||||
response_types: responseTypes,
|
||||
sector_identifier_uri: $('#sectorIdentifierUri input').val(),
|
||||
initiate_login_uri: $('#initiateLoginUri input').val(),
|
||||
post_logout_redirect_uri: $('#postLogoutRedirectUri input').val(),
|
||||
reuse_refresh_token: $('#reuseRefreshToken').is(':checked'),
|
||||
require_auth_time: $('#requireAuthTime input').is(':checked'),
|
||||
default_max_age: parseInt($('#defaultMaxAge input').val()),
|
||||
contacts: contacts,
|
||||
request_uris: this.requestUrisCollection.pluck('item'),
|
||||
default_acr_values: this.defaultAcrValuesCollection.pluck('item'),
|
||||
request_object_signing_alg: this.defaultToNull($('#requestObjectSigningAlg select').val()),
|
||||
userinfo_signed_response_alg: this.defaultToNull($('#userInfoSignedResponseAlg select').val()),
|
||||
userinfo_encrypted_response_alg: this.defaultToNull($('#userInfoEncryptedResponseAlg select').val()),
|
||||
userinfo_encrypted_response_enc: this.defaultToNull($('#userInfoEncryptedResponseEnc select').val()),
|
||||
id_token_signed_response_alg: this.defaultToNull($('#idTokenSignedResponseAlg select').val()),
|
||||
id_token_encrypted_response_alg: this.defaultToNull($('#idTokenEncryptedResponseAlg select').val()),
|
||||
id_token_encrypted_response_enc: this.defaultToNull($('#idTokenEncryptedResponseEnc select').val()),
|
||||
token_endpoint_auth_signing_alg: this.defaultToNull($('#tokenEndpointAuthSigningAlg select').val())
|
||||
};
|
||||
|
||||
// set all empty strings to nulls
|
||||
for (var key in attrs) {
|
||||
if (attrs[key] === "") {
|
||||
attrs[key] = null;
|
||||
}
|
||||
}
|
||||
|
||||
var _self = this;
|
||||
this.model.save(attrs, {
|
||||
success:function () {
|
||||
// switch to an "edit" view
|
||||
app.navigate('dev/dynreg/edit', {trigger: true});
|
||||
_self.remove();
|
||||
var view = new DynRegEditView({model: _self.model, systemScopeList: _self.options.systemScopeList});
|
||||
|
||||
view.load(function() {
|
||||
// reload
|
||||
$('#content').html(view.render().el);
|
||||
view.delegateEvents();
|
||||
});
|
||||
},
|
||||
error:function (error, response) {
|
||||
console.log("An error occurred when deleting from a list widget");
|
||||
|
||||
//Pull out the response text.
|
||||
var responseJson = JSON.parse(response.responseText);
|
||||
|
||||
//Display an alert with an error message
|
||||
$('#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
|
||||
"backdrop" : "static",
|
||||
"keyboard" : true,
|
||||
"show" : true // ensure the modal is shown immediately
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
render:function() {
|
||||
$(this.el).html(this.template({client: this.model.toJSON()}));
|
||||
|
||||
var _self = this;
|
||||
|
||||
// build and bind registered redirect URI collection and view
|
||||
_.each(this.model.get("redirectUris"), function (redirectUri) {
|
||||
_self.redirectUrisCollection.add(new URIModel({item:redirectUri}));
|
||||
});
|
||||
|
||||
$("#redirectUris .controls",this.el).html(new ListWidgetView({
|
||||
type:'uri',
|
||||
placeholder: 'https://',
|
||||
collection: this.redirectUrisCollection}).render().el);
|
||||
|
||||
// build and bind scopes
|
||||
var scopes = this.model.get("scope");
|
||||
var scopeSet = scopes ? scopes.split(" ") : [];
|
||||
_.each(scopeSet, function (scope) {
|
||||
_self.scopeCollection.add(new Backbone.Model({item:scope}));
|
||||
});
|
||||
|
||||
$("#scope .controls",this.el).html(new ListWidgetView({
|
||||
placeholder: 'new scope',
|
||||
autocomplete: _.uniq(_.flatten(this.options.systemScopeList.pluck("value"))),
|
||||
collection: this.scopeCollection}).render().el);
|
||||
|
||||
// build and bind contacts
|
||||
_.each(this.model.get('contacts'), function (contact) {
|
||||
_self.contactsCollection.add(new Backbone.Model({item:contact}));
|
||||
});
|
||||
|
||||
$("#contacts .controls", this.el).html(new ListWidgetView({
|
||||
placeholder: 'new contact',
|
||||
collection: this.contactsCollection}).render().el);
|
||||
|
||||
|
||||
// build and bind request URIs
|
||||
_.each(this.model.get('requestUris'), function (requestUri) {
|
||||
_self.requestUrisCollection.add(new URIModel({item:requestUri}));
|
||||
});
|
||||
|
||||
$('#requestUris .controls', this.el).html(new ListWidgetView({
|
||||
type: 'uri',
|
||||
placeholder: 'https://',
|
||||
collection: this.requestUrisCollection}).render().el);
|
||||
|
||||
// build and bind default ACR values
|
||||
_.each(this.model.get('defaultAcrValues'), function (defaultAcrValue) {
|
||||
_self.defaultAcrValuesCollection.add(new Backbone.Model({item:defaultAcrValue}));
|
||||
});
|
||||
|
||||
$('#defaultAcrValues .controls', this.el).html(new ListWidgetView({
|
||||
placeholder: 'new ACR value',
|
||||
// TODO: autocomplete from spec
|
||||
collection: this.defaultAcrValuesCollection}).render().el);
|
||||
|
||||
this.previewLogo();
|
||||
|
||||
// disable unsupported JOSE algorithms
|
||||
this.disableUnsupportedJOSEItems(app.serverConfiguration.request_object_signing_alg_values_supported, '#requestObjectSigningAlg option');
|
||||
this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_signing_alg_values_supported, '#userInfoSignedResponseAlg option');
|
||||
this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_encryption_alg_values_supported, '#userInfoEncryptedResponseAlg option');
|
||||
this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_encryption_enc_values_supported, '#userInfoEncryptedResponseEnc option');
|
||||
this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_signing_alg_values_supported, '#idTokenSignedResponseAlg option');
|
||||
this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_encryption_alg_values_supported, '#idTokenEncryptedResponseAlg option');
|
||||
this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_encryption_enc_values_supported, '#idTokenEncryptedResponseEnc option');
|
||||
this.disableUnsupportedJOSEItems(app.serverConfiguration.token_endpoint_auth_signing_alg_values_supported, '#tokenEndpointAuthSigningAlg option');
|
||||
|
||||
this.$('.nyi').clickover({
|
||||
placement: 'right',
|
||||
title: 'Not Yet Implemented',
|
||||
content: 'The value of this field will be saved with the client, '
|
||||
+'but the server does not currently process anything with it. '
|
||||
+'Future versions of the server library will make use of this.'
|
||||
});
|
||||
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
|
@ -67,7 +67,7 @@
|
|||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<div class="alert alert-error">
|
||||
<strong>Warning!</strong> You MUST protect your your Client ID, Client Secret, and your Registration Access Token. If
|
||||
<strong>Warning!</strong> You MUST protect your Client ID, Client Secret, and your Registration Access Token. If
|
||||
you lose your Client ID or Registration Access Token, you will no longer have access to your client's registration
|
||||
records and you will need to register a new client.
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,301 @@
|
|||
<!--
|
||||
Copyright 2014 The MITRE Corporation
|
||||
and the MIT Kerberos and Internet Trust Consortium
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!-- self-service resource registration -->
|
||||
|
||||
<script type="text/html" id="tmpl-rsreg">
|
||||
|
||||
<div class="row-fluid">
|
||||
|
||||
<div class="span5">
|
||||
<button class="btn btn-large" id="newreg">Register a new protected resource</button>
|
||||
</div>
|
||||
<div class="span2">
|
||||
<strong> - OR - </strong>
|
||||
</div>
|
||||
<div class="span5">
|
||||
<input type="text" id="clientId" placeholder="Enter Resource ID">
|
||||
<input type="text" id="regtoken" placeholder="Enter Registration Access Token">
|
||||
<button class="btn btn-large" id="editreg">Edit an existing protected resource</button>
|
||||
<span class="help-block>Paste in your ID and registration access token to access the resource's properties.</span>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/html" id="tmpl-rsreg-resource-form">
|
||||
|
||||
<h1><%=(client.client_id == null ? 'New' : 'Edit')%> Protected Resource</h1>
|
||||
|
||||
|
||||
<form class="form-horizontal tabbable">
|
||||
<fieldset>
|
||||
<div class="well well-small">
|
||||
<button class="btn btn-small btn-save btn-success"><i class="icon-ok-circle icon-white"></i> Save</button>
|
||||
<button class="btn btn-small btn-cancel"><i class="icon-ban-circle"></i> Cancel</button>
|
||||
<% if (client.client_id) { %>
|
||||
<button class="btn btn-danger btn-delete pull-right"><i class="icon-trash icon-white"></i> Delete</button>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a data-target="#resource-main-tab" data-toggle="tab" href="#">Main</a></li>
|
||||
<li><a data-target="#resource-access-tab" data-toggle="tab" href="#">Access</a></li>
|
||||
<li><a data-target="#resource-secret-tab" data-toggle="tab" href="#">Credentials</a></li>
|
||||
<li><a data-target="#resource-json-tab" data-toggle="tab" href="#">JSON</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="resource-main-tab">
|
||||
|
||||
<% if (client.client_id) { %>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<div class="alert alert-error">
|
||||
<strong>Warning!</strong> You MUST protect your resource ID, Secret, and your Registration Access Token. If
|
||||
you lose your ID or Registration Access Token, you will no longer have access to your resource's registration
|
||||
records and you will need to register a new resource.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="clientId">
|
||||
<label class="control-label">Client ID</label>
|
||||
<div class="controls">
|
||||
<pre><%=client.client_id ? client.client_id : '<code>Will be generated</code>'%></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="control-group" id="requireClientSecret">
|
||||
<label class="control-label">Client Secret</label>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<pre><%=client.client_id ? (client.client_secret ? client.client_secret : 'None (public client)') : 'Will be generated'%></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="clientConfigurationUri">
|
||||
<label class="control-label">Client Configuration URL</label>
|
||||
<div class="controls">
|
||||
<pre><%=client.registration_client_uri ? client.registration_client_uri : 'Will be generated'%></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="registrationAccessToken">
|
||||
<label class="control-label">Registration Access Token</label>
|
||||
<div class="controls">
|
||||
<pre><%=client.registration_access_token ? client.registration_access_token : 'Will be generated'%></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% } else { %>
|
||||
|
||||
<div class="control-group" id="clientId">
|
||||
<label class="control-label">ID</label>
|
||||
<div class="controls">
|
||||
<code>Will be generated</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="control-group" id="requireClientSecret">
|
||||
<label class="control-label">Secret</label>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<code>Will be generated</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="clientConfigurationUri">
|
||||
<label class="control-label">Configuration URL</label>
|
||||
<div class="controls">
|
||||
<code>Will be generated</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="registrationAccessToken">
|
||||
<label class="control-label">Registration Access Token</label>
|
||||
<div class="controls">
|
||||
<code>Will be generated</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% } %>
|
||||
|
||||
|
||||
<div class="control-group" id="clientName">
|
||||
<label class="control-label">Resource name</label>
|
||||
<div class="controls">
|
||||
<input value="<%=client.client_name ? client.client_name : ''%>" maxlength="100" type="text" class="" placeholder="Type something">
|
||||
<p class="help-block">Human-readable application name</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="clientDescription">
|
||||
<label class="control-label">Description</label>
|
||||
<div class="controls">
|
||||
<textarea class="input-xlarge" placeholder="Type a description" maxlength="200" rows="3"><%=client.client_description ? client.client_description : ''%></textarea>
|
||||
<p class="help-block">Human-readable text description</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="logoUri">
|
||||
<label class="control-label">Logo</label>
|
||||
<div class="controls">
|
||||
<input placeholder="https://" value="<%=client.logo_uri ? client.logo_uri : ''%>" maxlength="1000" type="text" class=""/>
|
||||
<p class="help-block">URL that points to a logo image, will be displayed on approval page</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="logoBlock">
|
||||
<div class="controls">
|
||||
<!-- TODO: this should be an internally-served placeholder graphic -->
|
||||
<img src="http://placehold.it/275x200&text=Enter a logo URL" alt="logo" id="logoPreview" width="275px" class="thumbnail" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="tosUri">
|
||||
<label class="control-label">Terms of Service</label>
|
||||
<div class="controls">
|
||||
<input placeholder="https://" value="<%=client.tos_uri ? client.tos_uri : ''%>" maxlength="1000" type="text" class=""/>
|
||||
<p class="help-block">URL for the Terms of Service of this client, will be displayed to the user</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="policyUri">
|
||||
<label class="control-label">Policy</label>
|
||||
<div class="controls">
|
||||
<input placeholder="https://" value="<%=client.policy_uri ? client.policy_uri : ''%>" maxlength="1000" type="text" class=""/>
|
||||
<p class="help-block">URL for the Policy Statement of this client, will be displayed to the user</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="clientUri">
|
||||
<label class="control-label">Home Page</label>
|
||||
<div class="controls">
|
||||
<input placeholder="https://" value="<%=client.client_uri ? client.client_uri : ''%>" maxlength="1000" type="text" class=""/>
|
||||
<p class="help-block">URL for the client's home page, will be displayed to the user</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="applicationType">
|
||||
<label class="control-label"><span class="label label-default nyi"><i class="icon-road icon-white"></i> NYI </span> Application Type</label>
|
||||
<div class="controls">
|
||||
<label class="radio inline">
|
||||
<input type="radio" name="applicationType" value="NATIVE" <%=(client.application_type == 'NATIVE' ? 'checked' : '')%>> Native
|
||||
</label>
|
||||
<label class="radio inline">
|
||||
<input type="radio" name="applicationType" value="WEB" <%=(client.application_type == 'WEB' ? 'checked' : '')%>> Web
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="contacts">
|
||||
<label class="control-label">Contacts</label>
|
||||
<div class="controls">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="resource-access-tab">
|
||||
|
||||
<div class="control-group" id="scope">
|
||||
<label class="control-label">Scope</label>
|
||||
<div class="controls">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="resource-secret-tab">
|
||||
|
||||
<div class="control-group" id="tokenEndpointAuthMethod">
|
||||
<label class="control-label">Introspection Endpoint Authentication Method</label>
|
||||
<div class="controls">
|
||||
<label class="radio">
|
||||
<input type="radio" name="tokenEndpointAuthMethod" value="client_secret_basic" <%=(client.token_endpoint_auth_method == 'client_secret_basic' ? 'checked' : '')%>> Client Secret over HTTP Basic
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="tokenEndpointAuthMethod" value="client_secret_post" <%=(client.token_endpoint_auth_method == 'client_secret_post' ? 'checked' : '')%>> Client Secret over HTTP POST
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="tokenEndpointAuthMethod" value="client_secret_jwt" <%=(client.token_endpoint_auth_method == 'client_secret_jwt' ? 'checked' : '')%>> Client Secret via symmetrically-signed JWT assertion
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="tokenEndpointAuthMethod" value="private_key_jwt" <%=(client.token_endpoint_auth_method == 'private_key_jwt' ? 'checked' : '')%>> Asymmetrically-signed JWT assertion
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="tokenEndpointAuthMethod" value="none" <%=(client.token_endpoint_auth_method == 'none' ? 'checked' : '')%>> No authentication
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="jwksUri">
|
||||
<label class="control-label">JWK Set</label>
|
||||
<div class="controls">
|
||||
<input placeholder="https://" value="<%=client.jwks_uri ? client.jwks_uri : ''%>" maxlength="1000" type="text" class=""/>
|
||||
<p class="help-block">URL for the client's JSON Web Key set</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="tokenEndpointAuthSigningAlg">
|
||||
<label class="control-label">Introspection Endpoint Authentication Signing Algorithm</label>
|
||||
<div class="controls">
|
||||
<select>
|
||||
<option value="default" <%=client.token_endpoint_auth_signing_alg == null ? 'selected ' : ''%>>Any allowed</option>
|
||||
<option value="HS256" <%=client.token_endpoint_auth_signing_alg == "HS256" ? 'selected' : ''%>>HMAC using SHA-256 hash algorithm</option>
|
||||
<option value="HS384" <%=client.token_endpoint_auth_signing_alg == "HS384" ? 'selected' : ''%>>HMAC using SHA-384 hash algorithm</option>
|
||||
<option value="HS512" <%=client.token_endpoint_auth_signing_alg == "HS512" ? 'selected' : ''%>>HMAC using SHA-512 hash algorithm</option>
|
||||
<option value="RS256" <%=client.token_endpoint_auth_signing_alg == "RS256" ? 'selected' : ''%>>RSASSA using SHA-256 hash algorithm</option>
|
||||
<option value="RS384" <%=client.token_endpoint_auth_signing_alg == "RS384" ? 'selected' : ''%>>RSASSA using SHA-384 hash algorithm</option>
|
||||
<option value="RS512" <%=client.token_endpoint_auth_signing_alg == "RS512" ? 'selected' : ''%>>RSASSA using SHA-512 hash algorithm</option>
|
||||
<option value="ES256" <%=client.token_endpoint_auth_signing_alg == "ES256" ? 'selected' : ''%>>ECDSA using P-256 curve and SHA-256 hash algorithm</option>
|
||||
<option value="ES384" <%=client.token_endpoint_auth_signing_alg == "ES384" ? 'selected' : ''%>>ECDSA using P-384 curve and SHA-384 hash algorithm</option>
|
||||
<option value="ES512" <%=client.token_endpoint_auth_signing_alg == "ES512" ? 'selected' : ''%>>ECDSA using P-512 curve and SHA-512 hash algorithm</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="resource-json-tab">
|
||||
|
||||
<pre>
|
||||
<%= JSON.stringify(client, undefined, 2) %>
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="well well-small">
|
||||
<button class="btn btn-small btn-save btn-success"><i class="icon-ok-circle icon-white"></i> Save</button>
|
||||
<button class="btn btn-small btn-cancel"><i class="icon-ban-circle"></i> Cancel</button>
|
||||
<% if (client.client_id) { %>
|
||||
<button class="btn btn-danger btn-delete pull-right"><i class="icon-trash icon-white"></i> Delete</button>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
</script>
|
Loading…
Reference in New Issue