The purpose of this sample project is to show you how to integrate a machine authentication flow with the FusionFabric.cloud Authorization Server, and call an API from FusionFabric.cloud, with the identity of the app.
If you want to go ahead, and you have a GitHub account, clone the following repository, and follow the instructions from ffdc-client-credentials/README.md. The link is: https://github.com/FusionFabric/ffdc-sample-nodejs .
The provided Github repository contains also a sample client application - ffdc-authorization-code, that demonstrates the implementation of the OAuth2 Authorization Code grant flow which is not covered in the current tutorial.
Prerequisites
For this application, you will use Express , a web framework for Node.js. Therefore, you must have Node , a version greater than v8.0.0, and npm installed on your computer.
You must also register an application on FusionCreator that includes the Referential Data API from the API Catalog.
Bootstrap App
Create a working directory and open it in a terminal or a command line:
This module uses the discover function of openid-client to connect to the Discovery service of FusionCreator.
Create a text file named .env, and add the following code, replacing the tokens with the corresponding values:
.env
# OpenID connection detailsCLIENT_ID="<%YOUR-CLIENT-ID%>"CLIENT_SECRET="<%YOUR-SECRET-KEY%>"AUTHORIZATION_WELLKNOWN ="https://api.fusionfabric.cloud/login/v1/sandbox/.well-known/openid-configuration"SCOPE="openid"# Data conectionBASE_URL="https://api.fusionfabric.cloud"# Running portPORT=3000
In the .env configuration file you store the variables that are passed to the openIdClient module to retrieve the authorization token. These are the following:
The CLIENT_ID and CLIENT_SECRET are the secrets of your application in FusionCreator.
You will write the templates that are used to render the pages of your client application in a later section.
Controller
In the controller, you define the call routes for the following endpoints of your client application: the root - /, the login - /login, the results - /results, and the logout - /logout.
In the code above, you start by defining an object to store the additional details required to get the access token: the grant type and the scope. The you use the openid-client client that you initialized in a previous section, to get the access token, by calling the grant() method. You then you store the access token in a local variable that you pass to the EJS template that will render the response. In the response page, auth, you display the access token.
The code illustrates the call to an API, in this case, the GetCountries endpoint of the Referential Data API. The access token is added to the headers of each subsequent call of the GETCountries endpoint. If the results are successfully fetched, they are passed to the view template to be displayed in the response page results. If an error occurs, the error page template is called.
To define the call route for the logout
In index.js add the following code:
index.js
app.get('/logout', (req, res) => {// Cleanup access token access_token =undefined// Back to index file res.render('pages/logout', { logout:"You successfully logged out" })});
In the logout route call, you simply reset the access token and redirect the browser to the logout page.
HTML Templates
In this section you configure the view engine of your client application.
You use an HTML templating engine, enabled by the EJS package.
EJS is configured to work with the templates stored in the views subdirectory of your main application directory.
To enable the view templates
At the root of your application, create the views directory with the following subdirectories and empty text files:
views/
pages/
auth.ejs
error.ejs
index.ejs
logout.ejs
results.ejs
partials/
footer.ejs
head.ejs
header.ejs
Add the following content to auth.ejs:
pages/auth.ejs
<html lang="en"><head><% include ../partials/head %></head><body class="container-fluid"><header><% include ../partials/header %></header><main class="main"><div><p><label>You successfully logged in with access token:</label></p><textarea id="textToken" rows="10" cols="100" wrap="soft"><%= token %></textarea><p></p><button type="button" onclick="myFunction()">Copy to clipboard</button><script>functionmyFunction() {document.getElementById("textToken").select()document.execCommand('copy') }</script></div></main><footer><% include ../partials/footer %></footer></body></html>
Add the following content to error.ejs:
pages/error.ejs
<html lang="en"><head><% include ../partials/head %></head><body class="container-fluid"><header><% include ../partials/header %></header><main class="main"><div class="row"><div class="col-sm-12"><div class="alert alert-danger" role="alert"><%= error %></div></div></main><footer><% include ../partials/footer %></footer></body></html>
Add the following content to index.ejs:
pages/index.ejs
<html lang="en"><head><% include ../partials/head %></head><body class="container-fluid"><header><% include ../partials/header %></header><footer><% include ../partials/footer %></footer></body></html>
Add the following content to logout.ejs:
pages/logout.ejs
<html lang="en"><head><% include ../partials/head %></head><body class="container-fluid"><header><% include ../partials/header %></header><main class="main"><div class="row"><div class="col-sm-12"><div class="alert alert-danger" role="alert"><%= error %></div></div></main><footer><% include ../partials/footer %></footer></body></html>
In this section, you learn how to use an enhanced authentication, that relies on asymmetric cryptography to authenticate your client application, without passing the client secret through the network. To learn more about private key authentication, see the dedicated section in the Platform Deep Dive guide.
To enable private key authentication in your client application
This lets you switch between the standard OAuth2 client credentials flow and the private key authentication flow by setting STRONG to True or False, in .env.
With the above code, you use a private RSA key to sign a JSON Web Token (JWT) that you send to the Authorization Server in exchange for the access token. The Authorization Server verifies your JWT with a public RSA key that you upload to your application.
Update the header.ejs template to account for the type of authentication when displaying the pages:
<html lang="en"><head><% include ../partials/head %></head><body class="container-fluid"><header><% include ../partials/header %></header><main class="main"><div><p><label>You successfully logged inwith access token:</label></p><textarea id="textToken" rows="10" cols="100" wrap="soft"><%= token %></textarea><p></p><button type="button" onclick="myFunction()">Copy to clipboard</button><script>functionmyFunction() {document.getElementById("textToken").select()document.execCommand('copy') }</script></div></main><footer><% include ../partials/footer %></footer></body></html>
pages/error.ejs
<html lang="en"><head><% include ../partials/head %></head><body class="container-fluid"><header><% include ../partials/header %></header><main class="main"><div class="row"><div class="col-sm-12"><div class="alert alert-danger" role="alert"><%= error %></div></div></main><footer><% include ../partials/footer %></footer></body></html>
pages/index.ejs
<html lang="en"><head><% include ../partials/head %></head><body class="container-fluid"><header><% include ../partials/header %></header><footer><% include ../partials/footer %></footer></body></html>
pages/logout.ejs
<html lang="en"><head><% include ../partials/head %></head><body class="container-fluid"><header><% include ../partials/header %></header><main class="main"><div class="row"><div class="col-sm-12"><div class="alert alert-danger" role="alert"><%= error %></div></div></main><footer>