WebCenters Portals REST API and WebCenter Content provide a great set of  web services enabling you to create rich interactive JavaScript components.

An issue you may have come across if you don’t have SSO enabled is the ability to interact against these services. This can be a problem if you are writing Javascript Widgets or hybrid mobile applications for WebCenter Portal that require authentication to access them.

You could present a popup requesting the user to re authenticate; however this isn’t ideal if the user has already authenticated with the portal to access your new JS Components.

Read on to see the options available to you –

There are two options available if you don’t use SSO:

1) Enabling AJAX pre-authentication on the WebCenter portal login page; which will store the authenticated session.
2) Setting up a trust service token and passing the authentication request with the token when you need to access the services once the user has authenticated.

 

1. Pre-authenticating against the REST API. 

1.1 Updating the login template for pre-auth.

On the login page disable the submit event on the form to authenticate against WebCenter Portal.
Instead when the user selects the login button –

1. Pass a base64 authentication request to the REST API via AJAX.
2. On a success response (store the REST API security token if needed)
3. Trigger the submit request to enable the form post to authenticate on WebCenter.

Here are some code samples for authenticating with either WebCenter Portal or Content via AJAX using JQuery –

WebCenter Portal AJAX REST API Authentication
(with OIT or Username & Password)

jquery.ajax({
	url: endpoint,
	dataType: 'json',
	beforeSend: function(xhr) {
		//if trust token not defined send base64 user/pass authentication
		if (FB.restInfo.trustServiceToken === undefined) {
			//pass user/password credentials
			if (username.length > 0) {
				//IE has no support for BTOA use crypto lib
				if (window.btoa === undefined) {
					xhr.setRequestHeader('Authorization', 'Basic ' + Crypto.util.bytesToBase64(Crypto.charenc.Binary.stringToBytes(username + ':' + password)));
				//all other browsers support BTOA
				} else {
					xhr.setRequestHeader('Authorization', 'Basic ' + window.btoa(username+':'+password));
				}
				return;
			}
		//else pass security token
		} else {
			//token auth
			xhr.setRequestHeader('Authorization', 'OIT ' + FB.restInfo.trustServiceToken); ///Obj path to Trust token value
		}

		//pass secure token
		xhr.withCredentials = true;
	},
	//Authentication Successful
	success: function(data) {
		//Process Resource Index Object in callback method
		//Store REST API Token
		callback(context);
	},
	//Authentication Failed
	error: function(request, status, error) {
		error_handler(callback)(request, status, error, endpoint);
	}
});

 

 WebCenter Content AJAX Authentication
(with OIT or Username & Password)

var params = {
	IdcService: 'PING_SERVER',
	IsJson: 1
};
//Authenticate with WebCenter Content
jquery.ajax({ url: endpoint+ '/idcplg', data: params, dataType: 'json',
	//user already authenticated
	success: function(data) {
		callback(this);
	},
	//Error connection or authorisation to WebCenter Content failed
	error: function(request, status, error) {
		//if trust token defined send OIT Auth Request
		if (FB.restInfo.trustServiceToken !== undefined) {
			//Authenticate Via OIT
			jquery.ajax({
				type: "GET",
				url: '/adfAuthentication', //http://domain.com/adfAuthentication will auth OIT on WebCenter
				//setup request headers first
				beforeSend: function(xhr) {
					xhr.setRequestHeader('Authorization', 'OIT ' + FB.restInfo.trustServiceToken); //Obj path to Trust token value
					xhr.withCredentials = true;
				},
				//request successfull
				success: function(data) {
					callback(this);
				},
				//issue with request
				error: function(request, status, error) {
					error_handler(callback)(request, status, error, endpoint+ '/idcplg');
				}
			});
		//else user/pass sent
		} else {
			//Authenticate with user/pass
			jquery.ajax({
				type: "POST",
				url: endpoint+'/login/j_security_check',
				data: {
					j_username: 		username,
					j_password: 		password,
					j_character_encoding: 	'UTF-8'
				},
				//request successfull
				success: function(data) {
					callback(this);
				},
				//issue with request
				error: function(request, status, error) {
					error_handler(callback)(request, status, error, endpoint+ '/idcplg');
				}
			});
		}
	}
});

The WebCenter Content Secure Token Auth requires authentication on http://domain.com/adfAuthentication.

You can also use this to authenticate against the Inbound Refinery (Conversion Server)
http://domain.com/ibr/adfAuthentication

And Universal Records Management
http://domain.com/urm/adfAuthentication

Where as User/Pass Auth on the content server is requested via http://domain.com/cs/login/j_security_check.

Here is a simple example of a webcenter login page that makes an Authentication request first to the REST API before posting the form and logging into WebCenter Portal.

 

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

    <title>Login Auth Example</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">

</head>
<body>

<div id="FB-loginWrapper">
	<h2>Sign-in to your account</h2>

	<form name="PortalLoginForm" method="post" action="/webcenter/wcAuthentication">
		<input type="hidden" name="success_url" value="/webcenter/intranet_loginhandlerservlet"/>
		<input type="hidden" name="j_character_encoding" value="UTF-8">

		<div class="formField">
			<label>Username:</label>
			<input type="text" name="j_username" />
		</div>

		<div class="formField">
			<label>Password:</label>
			<input type="password" name="j_password" />
		</div>

		<input disabled="disabled" type="submit" />
	</form>
</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.10.2.min.js"><\/script>')</script>
<script src="js/vendor/cryptojs.js"></script>

<script>
//Setup JS namespace
var FB = FB || {};
FB.Login = (function() {
	return {
		//on script init
		init: function() {
			//Setup page events
			this.events();

			//remove disabled attr on submit button.
			$('[name="PortalLoginForm"] [type="submit"]').prop('disabled',false);
		},
		//setup page events
		events: function() {
			//on submit click initialise auth request
			$('[name="PortalLoginForm"]').submit(function() {
				//if data attribute true on form allow submit
				if ($(this).data('valid')) {
					return true;
				}

				//call REST API authentication method
				FB.Login.AuthRestAPI(
					'/rest/api/resourceIndex', 			//endpoint
					$('[name="j_username"]').val(), 	//User
					$('[name="j_password"]').val(), 	//Pass
					function() { //callback method
						$('[name="PortalLoginForm"]').data('valid', true).submit(); //enable form to submit
						$('[name="PortalLoginForm"] [type="submit"]').submit(); //submit form on AuthRestAPI success AJAX.
					}
				);

				//else stop form from submitting
				return false;
			});
		},
		//REST Auth AJAX method
		AuthRestAPI:function(endpoint, username, password, callback) {
			//make ajax req
			$.ajax({
				url: endpoint,
				dataType: 'json',
				beforeSend: function(xhr) {
					//IE has no support for BTOA use cryptoJS lib
					if (window.btoa === undefined) {
						xhr.setRequestHeader('Authorization', 'Basic ' + Crypto.util.bytesToBase64(Crypto.charenc.Binary.stringToBytes(username + ':' + password)));
					//all other browsers support BTOA
					} else {
						xhr.setRequestHeader('Authorization', 'Basic ' + window.btoa(username+':'+password));
					}

					//pass secure token
					xhr.withCredentials = true;
				},
				//Authentication Successful
				success: function(data) {
					//submit form via callback
					callback();
				},
				//Authentication Failed
				error: function(request, status, error) {
					alert('Authentication failed');
				}
			});
		}
	}
})();

//on DOM Loaded setup page
$(document).ready(function() {
	FB.Login.init();
});
</script>

</body>
</html>

 

2. Setting up the the trust service security token
(Info to setup OIT).

I would recommend setting up the trust token; however the base64 authentication pre login above is easier and quicker to setup.

The trust token will be generated once the user has logged in.

2.1. Create keystore

a) cd /opt/oracle/jrmc-4.0.1-1.6.0/bin/
b) keytool -genkeypair -keyalg RSA -dname “cn=spaces,dc=domain,dc=com” -alias orakey -keypass myKeyPassword -keystore /opt/oracle/keystore/default-keystore.jks -storepass myKeyPassword -validity 1064
c) keytool -exportcert -v -alias orakey -keystore /opt/oracle/keystore/default-keystore.jks -storepass myKeyPassword -rfc -file /opt/oracle/keystore/orakey.cer
d) keytool -importcert -alias webcenter_spaces_ws -file /opt/oracle/keystore/orakey.cer -keystore /opt/oracle/keystore/default-keystore.jks -storepass myKeyPassword

2.2. Update jps-config.xml

a)

<serviceInstance name="keystore" provider="keystore.provider" location="/opt/oracle/keystore/default-keystore.jks">
<description>Default JPS Keystore Service</description>

b)

<propertySets>
	<propertySet name="trust.provider.embedded">
		... existing entries
		<property value="orakey" name="trust.aliasName"/>
		<property value="orakey" name="trust.issuerName"/>
	</propertySet>
</propertySets>

 

2.3. Update credential store

a) in WLST: /opt/oracle/middleware/Oracle_WC1/common/bin/wlst.sh
b) connect()
c) updateCred(map=”oracle.wsm.security”, key=”keystore-csf-key”, user=”owsm”, password=”myKeyPassword “, desc=”Keystore key”)
d) updateCred(map=”oracle.wsm.security”, key=”enc-csf-key”, user=”orakey”, password=”myKeyPassword “, desc=”Encryption key”)
e) updateCred(map=”oracle.wsm.security”, key=”sign-csf-key”, user=”orakey”, password=”myKeyPassword “, desc=”Signing key”)

2.4. Add TrustServiceIdentityAsserter.

a) Console -> Security Realms -> myrealm -> Providers -> New
b) Restart all

2.5. Configure Credential Store

a) in WLST: /opt/oracle/middleware/Oracle_WC1/common/bin/wlst.sh
b) connect()
c) createCred(map=”o.webcenter.jf.csf.map”, key=”keygen.algorithm”,user=”keygen.algorithm”, password=”AES”)
d) createCred(map=”o.webcenter.jf.csf.map”, key=”cipher.transformation”,user=”cipher.transformation”, password=”AES/CBC/PKCS5Padding”)

2.6. Test it against the rest api

a) http://www.domain.com/rest/api/resourceIndex

Once setup create a bean to output the token into the page template  ie ${fb_rtc_bean.trustServiceToken} JS object so that your JS AJAX request can reuse it.

var FB = FB || {};
FB.restInfo = {
	username: 				'${securityContext.userName}',
	trustServiceToken:			'${fb_rtc_bean.trustServiceToken}',
	spaceName: 				'${spaceContext.currentSpaceName}',
	spaceGUID: 				'${spaceContext.currentSpace.metadata.guid}'
};

You can then use one of the AJAX authentication methods above with ${fb_rtc_bean.trustServiceToken} reading the JS Obj FB.restInfo.trustServiceToken;