Source: src/main/javascript/oracle/oj/ojmodel/OAuth.js

Oracle® JavaScript Extension Toolkit (JET)
1.1.2

E65298-01

/**
 * Copyright (c) 2014, Oracle and/or its affiliates.
 * All rights reserved.
 */

/*jslint browser: true*/
/*global jQuery:false*/

/**
 * @export
 * @class oj.OAuth
 * @classdesc Member of Model objects. Object representing name/value pairs for a data service record
 *
 * @param {Object} attributes Initial set of attribute/value pairs with which to seed this OAuth object 
 * @param {string} header Actual name for the Authorization header (default 'Authorization') 
 * @example <caption>Initialize OAuth with client credentials</caption>
 * var myOAuth = new oj.OAuth('X-Authorization', {...Clent Credentials ...});
 * 
 * @example <caption>Initialize OAuth with access_token</caption>
 * var myOAuth = new oj.OAuth('X-Authorization', {...Access Token...});
 * 
 * @example <caption>Initialize empty OAuth and set access_token</caption>
 * var myOAuth = new oj.OAuth();
 * myOAuth.setAccessTokenResponse({...Access Token...});
 *
 * @constructor
 */
oj.OAuth = function(header, attributes) 
{
	attributes = attributes || {};
	header = header || 'Authorization';
	oj.OAuth._init(this, attributes, header);
};

// Subclass from oj.Object 
oj.Object.createSubclass(oj.OAuth, oj.Object, "oj.OAuth");
oj.OAuth.prototype.Init = function()
{
    oj.OAuth.superclass.Init.call(this);
};

/**
 * Calculates Authorization header based on client credentials or access_token
 * @return {Object} OAuth 2.0 Authorization header
 * @example <caption>Get Authorization header</caption>
 * myOAuth.getHeader();
 *
 * @export
 */
oj.OAuth.prototype.getHeader = function() 
{
	var headers = {};
	if(!this.accessTokenResponse['access_token']) {
		this.clientCredentialGrant();
	}
	headers[this.accessTokenRequest.auth_header]='Bearer '+this.accessTokenResponse['access_token'];
	return headers;
}

/**
 * Check is OAuth initialized (not null access_token).
 * @return {boolean} true/false
 * @example <caption>Check if OAuth initialized</caption>
 * if(myOAuth.isInitialized()) console.log('Initialized');
 *
 * @export
 */
oj.OAuth.prototype.isInitialized = function() 
{
	return (this.accessTokenResponse.access_token) ? true : false;
}

/**
 * Request for access_token(bearer token) using Client Credential Authorization Grant.
 * Initialize response part of the OAuth object (access_token, e.t.c.)
 * @example <caption>Set/Re-set response part of the OAuth object using Client Credentials</caption>
 * myOAuth.clientCredentialGrant();
 *
 * @export
 */
oj.OAuth.prototype.clientCredentialGrant = function() 
{
	var headers = {}, self = this;
	headers[self.accessTokenRequest.auth_header] = 'Basic ' + 
		oj.OAuth._base64_encode(self.accessTokenRequest['client_id']+':'+self.accessTokenRequest['client_secret']);
		
	$.ajax({
		type: 'POST',
		async: false,
		url: this.accessTokenRequest['bearer_url'],
		data: 'grant_type=client_credentials',
		headers: headers,
		success:function(data) {
			oj.OAuth._initAccessToken(self.accessTokenResponse, data);
		},
		error: function(jqXHR, textStatus, errorThrown) {
			throw new Error(jqXHR.responseText);
		}
	});	

}

/**
 * Set response part of the OAuth object (access_token, e.t.c.)
 * @param {Object} data current response
 * @example <caption>'Initialize' response part of the OAuth object with access_token</caption>
 * myOAuth.setAccessTokenResponse({...Access Token...});
 *
 * @export
 */
oj.OAuth.prototype.setAccessTokenResponse = function(data) 
{
	oj.OAuth._initAccessToken(this.accessTokenResponse, data);
}

/**
 * Get response part of the OAuth object (access_token, e.t.c.)
 * @return {Object} cached response
 * @export
 */
oj.OAuth.prototype.getAccessTokenResponse = function()
{
	return this.accessTokenResponse;
}

/**
 * Clean response part of the OAuth object (access_token, e.t.c.)
 * Null and remove all data from response part of the OAuth object
 * @export
 */
oj.OAuth.prototype.cleanAccessTokenResponse = function()
{
	oj.OAuth._cleanAccessToken(this.accessTokenResponse);
}

/**
 * Set request part of the OAuth object (client credentials, uri endpoint)
 * @param {Object} data current client credentials and uri
 * @example <caption>'Initialize' request part of the OAuth object with client credentials and calculate access_token</caption>
 * myOAuth.setAccessTokenRequest({...Clent Credentials ...});
 * myOAuth.clientCredentialGrant();
 *
 * @export
 */
oj.OAuth.prototype.setAccessTokenRequest = function(data) 
{
	oj.OAuth._initAccessToken(this.accessTokenRequest, data);
}

/**
 * Get request part of the OAuth object (client credentials, uri endpoint)
 * @return {Object} cached request
 * @export
 */
oj.OAuth.prototype.getAccessTokenRequest = function()
{
	return this.accessTokenRequest;
}

/**
 * Clean request part of the OAuth object (client credentials, uri endpoint)
 * Null and remove all data from request part of the OAuth object
 * @export
 */
oj.OAuth.prototype.cleanAccessTokenRequest = function()
{
	oj.OAuth._cleanAccessToken(this.accessTokenRequest);
}

/**
 * @private
 * @param {Object} oauth
 * @param {Object} attributes
 * @param {string||null} header
 */
oj.OAuth._init = function(oauth, attributes, header) 
{
	oauth.Init();
	oauth.accessTokenRequest = {};
	oauth.accessTokenResponse = {};
	
	if(attributes['access_token']) { // access_token has higher preference
		oj.OAuth._initAccessToken(oauth.accessTokenResponse, attributes);
	} else if(attributes['client_id'] && attributes['client_secret'] && attributes['bearer_url']) { // Client Credential Grant		
		oj.OAuth._initAccessToken(oauth.accessTokenRequest, attributes);
	}
	oauth.accessTokenRequest.auth_header = header;
}

/**
 * @private
 * @param {Object} oauthObj - Request/Response object to deal with
 * @param {Object} data - object to populate
 */
oj.OAuth._initAccessToken = function(oauthObj, data) {
	var prop;
	data = data || {};
	for (prop in data) {
		oauthObj[prop] = data[prop];
	}
}

/**
 * @private
 * @param {Object} oauthObj - Request/Response object to deal with
 */
oj.OAuth._cleanAccessToken = function(oauthObj) {
	var key;
	for (key in oauthObj) {
		if (oauthObj.hasOwnProperty(key)) {
			if(key !== 'auth_header') {
				oauthObj[key] = null;
				delete oauthObj[key];
			}
		}
	}
}

/**
 * @private
 * @param {string} a The data to calculate the base64 representation from
 * @return {string} The base64 representation
 */
 oj.OAuth._base64_encode = function (a) {
	var d, e, f, b, g = 0,
		h = 0,
		i = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
		c = [];
	do {
		d = a.charCodeAt(g++);
		e = a.charCodeAt(g++);
		f = a.charCodeAt(g++);
		b = d << 16 | e << 8 | f;
		d = b >> 18 & 63;
		e = b >> 12 & 63;
		f = b >> 6 & 63;
		b &= 63;
		c[h++] = i.charAt(d) + i.charAt(e) + i.charAt(f) + i.charAt(b);
	} while (g < a.length);
	c = c.join("");
	d = a.length % 3;
	return (d ? c.slice(0, d - 3) : c) + "===".slice(d || 3);	
}