All Downloads are FREE. Search and download functionalities are using the official Maven repository.

static.resources.js.rsreg.js Maven / Gradle / Ivy

Go to download

Thymeleaf UI for spring boot autoconfiguration version of the OpenID Connect Server reference implementation at https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server

The newest version!
/*******************************************************************************
 * Copyright 2015 The MITRE Corporation
 *   and the MIT 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.
 *******************************************************************************/
var ResRegClient = Backbone.Model.extend({
    idAttribute: "client_id",

    defaults:{
        client_id:null,
        client_secret:null,
        client_name:null,
        client_uri:null,
        logo_uri:null,
        contacts:[],
        tos_uri:null,
        token_endpoint_auth_method:null,
        scope:null,
        policy_uri:null,
        
        jwks_uri:null,
        jwks:null,
        jwksType:'URI',
        
        application_type: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(options) {
    	this.options = options;
		
	},
	
	events:{
		"click #newreg":"newReg",
		"click #editreg":"editReg"
	},
	
	load:function(callback) {
    	if (this.options.systemScopeList.isFetched) {
    		callback();
    		return;
    	}

    	$('#loadingbox').sheet('show');
    	$('#loading').html('' + $.t('common.scopes') + ' ');

    	$.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());
        $(this.el).i18n();
    	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 ResRegClient({
			client_id: clientId,
			registration_access_token: token
		});
		
		var self = this;
		
		client.fetch({success: function() {
			
	        if (client.get("jwks")) {
	        	client.set({
	        		jwksType: "VAL"
	        	}, { silent: true });
	        } else {
	        	client.set({
	        		jwksType: "URI"
	        	}, { silent: true });
	        }
			
	    	var view = new ResRegEditView({model: client, systemScopeList: app.systemScopeList}); 
	    	
	    	view.load(function() {
	    		$('#content').html(view.render().el);
	    		view.delegateEvents();
	    		setPageTitle($.t('rsreg.new'));
	    		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(options) {
    	this.options = options;
        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();
        
        this.listWidgetViews = [];
	},
	
	load:function(callback) {
    	if (this.options.systemScopeList.isFetched) {
    		callback();
    		return;
    	}

    	$('#loadingbox').sheet('show');
    	$('#loading').html('' + $.t('common.scopes') + ' ');

    	$.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":"cancel",
        "click .btn-delete":"deleteClient",
        "change #logoUri input":"previewLogo",
        "change #tokenEndpointAuthMethod input:radio":"toggleClientCredentials",
        "change #jwkSelector input:radio":"toggleJWKSetType"
    },

    cancel:function(e) {
    	e.preventDefault();
    	app.navigate('dev/resource', {trigger: true});
    },
    
    deleteClient:function (e) {
    	e.preventDefault();

        if (confirm($.t('client.client-table.confirm'))) {
            var self = this;

            this.model.destroy({
            	dataType: false, processData: false,
                success:function () {
                	self.remove();
                	app.navigate('dev/resource', {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
        			 });
            	}
            });

        }

        return false;
    },

    previewLogo:function() {
    	if ($('#logoUri input', this.el).val()) {
    		$('#logoPreview', this.el).empty();
    		$('#logoPreview', this.el).attr('src', $('#logoUri input', this.el).val());
    	} else {
    		//$('#logoBlock', this.el).hide();
    		$('#logoPreview', this.el).attr('src', 'resources/images/logo_placeholder.gif');
    	}
    },

    /**
     * Set up the form based on the current state of the tokenEndpointAuthMethod parameter
     * @param event
     */
    toggleClientCredentials:function() {
    	
        var tokenEndpointAuthMethod = $('#tokenEndpointAuthMethod input', this.el).filter(':checked').val();
        
        // show or hide the signing algorithm method depending on what's selected
        if (tokenEndpointAuthMethod == 'private_key_jwt'
        	|| tokenEndpointAuthMethod == 'client_secret_jwt') {
        	$('#tokenEndpointAuthSigningAlg', this.el).show();
        } else {
        	$('#tokenEndpointAuthSigningAlg', this.el).hide();
        }
    },
    
    /**
     * Set up the form based on the JWK Set selector 
     */
    toggleJWKSetType:function() {
    	var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val();
    	
    	if (jwkSelector == 'URI') {
    		$('#jwksUri', this.el).show();
    		$('#jwks', this.el).hide();
    	} else if (jwkSelector == 'VAL') {
    		$('#jwksUri', this.el).hide();
    		$('#jwks', this.el).show();
    	} else {
    		$('#jwksUri', this.el).hide();
    		$('#jwks', 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;
    	}
    },

    saveClient:function (e) {
    	e.preventDefault();

        $('.control-group').removeClass('error');

        // sync any leftover collection items
        _.each(this.listWidgetViews, function(v) {
        	v.addItem($.Event('click'));
        });
        
        // build the scope object
        var scopes = this.scopeCollection.pluck("item").join(" ");
        
        var contacts = this.contactsCollection.pluck('item');
        var userInfo = getUserInfo();
        if (userInfo && userInfo.email) {
        	if (!_.contains(contacts, userInfo.email)) {
        		contacts.push(userInfo.email);
        	}
        }

        // process the JWKS
        var jwksUri = null;
        var jwks = null;
        var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val();
    	
    	if (jwkSelector == 'URI') {
            jwksUri = $('#jwksUri input').val();
    		jwks = null;
    	} else if (jwkSelector == 'VAL') {
    		jwksUri = null;
    		try {
    			jwks = JSON.parse($('#jwks textarea').val());
    		} catch (e) {
        		console.log("An error occurred when parsing the JWK Set");

        		//Display an alert with an error message
				$('#modalAlert div.modal-header').html("JWK Set Error");
        		$('#modalAlert div.modal-body').html("There was an error parsing the public key from the JSON Web Key set. Check the value and try again.");
        		
    			 $("#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;
    		}
    	} else {
    		jwksUri = null;
    		jwks = null;
    	}

        var attrs = {
            client_name:$('#clientName input').val(),
            logo_uri:$('#logoUri input').val(),
            scope: scopes,
            client_secret: null, // never send a client secret
            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,
            jwks: jwks,
            token_endpoint_auth_method: $('#tokenEndpointAuthMethod input').filter(':checked').val(),
            contacts: contacts,
            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/resource/edit', {trigger: true});
            	_self.remove();

            	if (_self.model.get("jwks")) {
    	        	_self.model.set({
    	        		jwksType: "VAL"
    	        	}, { silent: true });
    	        } else {
    	        	_self.model.set({
    	        		jwksType: "URI"
    	        	}, { silent: true });
    	        }
        		
    			var view = new ResRegEditView({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(), userInfo: getUserInfo()}));
		
		this.listWidgetViews = [];
		
		var _self = this;

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

        var scopeView = new ListWidgetView({
        	placeholder: $.t('client.client-form.scope-placeholder'), 
        	autocomplete: _.uniq(_.flatten(this.options.systemScopeList.unrestrictedScopes().pluck("value"))), 
        	helpBlockText: $.t('rsreg.client-form.scope-help'),
            collection: this.scopeCollection});
        $("#scope .controls",this.el).html(scopeView.render().el);
        this.listWidgetViews.push(scopeView);

        // build and bind contacts
        _.each(this.model.get('contacts'), function (contact) {
        	_self.contactsCollection.add(new Backbone.Model({item:contact}));
        });
        
        var contactView = new ListWidgetView({
        	placeholder: $.t('client.client-form.contacts-placeholder'),
        	helpBlockText: $.t('client.client-form.contacts-help'),
        	collection: this.contactsCollection});
        $("#contacts .controls", this.el).html(contactView.render().el);
        this.listWidgetViews.push(contactView);
        
        
        this.toggleClientCredentials();
        this.previewLogo();
        this.toggleJWKSetType();
        
        // disable unsupported JOSE algorithms
        this.disableUnsupportedJOSEItems(app.serverConfiguration.token_endpoint_auth_signing_alg_values_supported, '#tokenEndpointAuthSigningAlg option');
        
        this.$('.nyi').clickover({
        	placement: 'right', 
            title: $.t('common.not-yet-implemented'),
            content: $.t('common.not-yet-implemented-content')
        	});
        

        $(this.el).i18n();
        return this;
	}
	
});




© 2015 - 2024 Weber Informatics LLC | Privacy Policy