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;

