Oracle VBCS is already very tightly coupled with Oracle Fusion SaaS applications; in that you can make REST calls back into Oracle Fusion as the "logged in user" without any special code - it’s just configuration. This is important and sometimes you need to make calls to Fusion "as" the logged in user.
All this is good but there are times when it’s not possible to setup Oracle VBCS in a way that enables this identity propagation. Additionally, there are times when we need to generate a authorization token that we need to send to another system so that "it" can execute a REST call to Oracle Fusion as that user.
We faced this issue in our Microsoft Teams Fusion Integration (link) where we needed to make calls back to Oracle Fusion from Oracle Integration cloud as the logged in user and this technique documented below helped us.
The way we solved this in our Microsoft Teams Fusion Integration V2 release is by using the OAuth 2.0 Authorization Code flow. In this scenario we assume that the user has "single sign on" configured with an IDCS server which is associated with Oracle Fusion.
The general OAuth Authorization flow is:
There are principally two use cases where this technique can be used
Visual Builder Implementation
The next section details how the OAuth authentication flow can be implemented in VB. The detail below assumes the reader is familiar with VB development however detailed OCI IAM steps are provided.
Within Oracle OCI IAM there are two types of OAuth applications you can implement. A confidential application and a mobile application. For our use case we must use the “mobile” application as client is not considered secure, we need a solution which does not require the OAuth client secret
Log into Oracle OCI IAM and within Integrated Applications create an OCI IAM Mobile app
You can now test the OAuth flow in postman. This is recommended so that we are sure everything else is working before we start with VB.
Within postman :
At the bottom of the Security section, you will see a button called “Get New Access Token”, pressing this will make postman obtain a new token with which you can use it in your REST call.
If you have any errors, check the postman console for clues into what the error is and resolve this before continuing.
Now it’s time to create the sample VBCS application. The VB application has several components which we will be using.
At the VB application level, create the following variables. These variables are used to store various configuration parameters, several required parameters for OAuth
Variable Name |
Sample Value |
Usage |
URL Parameter |
code |
Default Value = NOT-SET |
This value is sent back from OCI IAM from the redirect |
Yes |
iam_base_url |
<your OCI IAM hostname> |
This is the hostname of your OCI IAM server. |
No |
iam_client_id |
<from OCI IAM console> |
We need this to identify the client on OCI IAM |
No |
iam_codeverifier |
123456789012345678901234567890 |
This needs to a random set of more than 43 characters |
No |
jwt_token |
Empty |
This variable is set with the JWT token |
No |
parameter1 |
Anything you want |
A sample URL parameter |
Yes |
parameter1 |
Anything you want |
A sample URL parameter |
Yes |
state |
Default Value = NOT-SET |
We will use this to preserve the URL parameters to the application |
Yes |
On this screen add three text fields to the page and map each field to the following variables
This endpoint exchanges the received authentication code from OCI IAM with a JWT token.
{ "id_token": "eyJraWQiO..........vMZQ", |
At the Application level create a “VB Enter” Event listener trigger, using JavaScript, and enter this JavaScript code.
define([
'vb/action/actionChain',
'vb/action/actions',
'vb/action/actionUtils',
], (
ActionChain,
Actions,
ActionUtils
) => {
'use strict';
class vbenter_chain extends ActionChain {
async run(context) {
const { $application } = context;
let state = {};
if ($application.variables.code === "NOT-SET") {
//
// if code is not set then that means we were not redirected back to VB so its the first time
//
console.log('no code set');
// Store the current state of URL parameters (parameter1 & parameter2) into a state variable
state = {
'parameter1': encodeURI($application.variables.parameter1),
'parameter2': encodeURI($application.variables.parameter2)
};
// Call OCI IAM authorize endpoint, passing state etc requesting a token
//
await Actions.openUrl(context, {
url: "https://" + $application.variables.iam_base_url +
"/oauth2/v1/authorize?response_type=code" +
"&client_id=" + $application.variables.iam_client_id +
"&code_challenge=" + $application.variables.iam_codeverifier +
"&scope=" + $application.variables.fa_iam_scope +
"&redirect_uri=" + encodeURI("https://" + window.location.hostname + window.location.pathname) +
"&state=" + JSON.stringify(state),
});
// Processing terminates above as application has now been redirected to OCI IAM
}
// If state variable is not NOT-SET then we have state back from OCI IAM, we need to process it and request a token
if ($application.variables.state !== 'NOT-SET') {
// We're returning from oauth redirect, restore state
// Restore State
state = JSON.parse($application.variables.state);
console.log("****************** RESTORED STATE = " + JSON.stringify(state));
$application.variables.parameter1 = decodeURI(state.parameter1);
$application.variables.parameter2 = decodeURI(state.parameter2);
// Now call OCI IAM and request a token using the authorization code
// Notes :
// - We override contentType to be application/x-www-form-urlencoded
// - Redirect URL must be URI encoded
//
const callRestGetJWTPostTokenResult = await Actions.callRest(context, {
endpoint: 'getJWT/postToken',
uriParams: {},
contentType: "application/x-www-form-urlencoded",
body: "code=" + encodeURIComponent($application.variables.code) +
"&grant_type=authorization_code&client_id=" + $application.variables.iam_client_id +
"&code_verifier=" + $application.variables.iam_codeverifier +
"&redirect_uri=" + encodeURI("https://"+window.location.hostname+window.location.pathname),
});
if (callRestGetJWTPostTokenResult.status !== 200) {
// If not 200 response them we had an error getting a JWT token
await Actions.fireNotificationEvent(context, {
summary: 'Error calling OCI IAM token server, please contact your administrator for help',
});
console.log("******************************error unable to get token");
return vbenter_chain; // Return prematurely
}
if (callRestGetJWTPostTokenResult.body.access_token === undefined) {
// Not the right body
await Actions.fireNotificationEvent(context, {
summary: 'Error getting Token from OCI IAM,
message: 'Error parsing token from OCI IAM token service, please contact your administrator for more assistance',
});
return vbenter_chain;
}
// So far so good, extract the OAuth(JWT) token from payload and assign it to the global variable,
// which in turn is shown in the UI
$application.variables.jwttoken = callRestGetJWTPostTokenResult.body.access_token;
}
}
}
return vbenter_chain;
});
This commented code does the following:
The first time you run the application it will give an error, this is normal. This is because the redirect URL which is being sent to Oracle OCI IAM is not recognised, we only added the postman redirect URL.
OCI IAM will however tell us what URL was passed as part of the error and we can use this. We now need to copy this URL and add it to the list of “Redirect URLs” within the OAuth application we created earlier.
When running the application, the second time we should see:
You can now use this OAuth JWT token to call Fusion Applications from either VB or passing it securely to another application so it can call Oracle Fusion Applications.
Warning: NEVER pass the JWT token via URL parameters always send it as part of a HTTPS request, you should send it either in a header variable or in the payload body. If you send the JWT token as part of the URL, i.e., a URL parameter, then it can easily be seen in the browsers history and many access logs along the route to the calling service and hence a security risk.
Quick Note About Redirect URLs
Within OCI IAM you need to enter a valid redirect URL, however within a VB ecosystem only the “live” URL stays the same. Preview and stage URLs contain the version number within it so if you make a new version of the application you will need to add a new redirect URL to OCI IAM. Generally, I tend to only stage my applications and only publish live when finished.
Conclusion
This blog post describes how you can implement 3 Legged OAuth within VB to get a OAuth JWT token which you can use to call Fusion Applications REST APIs. Whilst VB doesn’t really need this technique, as it automatically does this for you, there are instances when VB isn’t configured in this way, or you need to obtain a OAuth JWT token to pass to a downstream server.
Any questions send me an email!
25+ years of Oracle experience, specialising in Technical design and design authority of Oracle Technology solutions, specialising in integrating technology with Oracles SaaS products.
Extensive credible communication skills at all levels, from hard core developers to C-Level executives.
Specialities: Oracle Fusion Apps Integration, Oracle Cloud products, SaaS Integration architectures, Engaging with SIs & ISVs, Technical Enablement, Customer Design Reviews, advisory and project coaching.
TOGAF 9 Architect and Oracle Cloud Infrastructure Architect Certified
Next Post