This project is an example of how to connect to Banno services using OpenID Connect (an identity layer on top of OAuth 2.0).
This repository includes an example that uses Node.js with the Passport authentication middleware to handle the OpenID Connect protocol.
This example is best used when following along with the Authentication Quickstart on JackHenry.Dev.
If you're learning how to build a plugin, you should use this other example project - https://github.com/Banno/simple-plugin-example
Before you get started, you'll need these credentials:
client_id
client_secret
You have a few different options for getting those credentials.
Instructions on how to sign up for a developer account on JackHenry.Dev are at https://jackhenry.dev/open-api-docs/accessing-the-digital-toolkit/.
You'll have to get the credentials from the back office administrator at your financial institution who has access to Banno People.
If the administrator does not know where to do this, they can review the External application configuration article on the Banno Knowledge site.
It is important to keep the `client_secret` value secret and not leak it through some kind of frontend, client-accessible JavaScript call.
The example is built for Node.js and npm.
If you don't have these installed on your system already, you may want to install a Node Version Manager such as nvm.
The cloned repository includes everything that you need for the next step.
From the repository root folder, run this command in the terminal:
npm install
After you've completed the installation steps, run this command in the terminal from the repository root folder:
npm start
The server will now be running locally. You'll see this log statement in the terminal:
Environment: local
Server listening on http://localhost:8080...
Next, go to http://localhost:8080/login.html in a web browser.
Click on Sign in with Banno
and sign in with your Banno Username and Password.
Once you are signed in, you'll be redirected to http://localhost:8080/me and see the OpenID Connect claims for the user. It'll look similar to the following example:
{
"sub": "5cad5c30-6d24-11e9-870c-0242b78f8571",
"address": {
"locality": "Seattle",
"postal_code": "981090000",
"region": "WA",
"street_address": "400 Broad St"
},
"email": "[email protected]",
"phone_number": "+15552368",
"birthdate": "1951-03-02",
"family_name": "Doe",
"given_name": "Riley",
"locale": "en-US",
"name": "Riley Doe",
"picture": "https://digital.garden-fi.com/a/consumer/api/node/public-profile-photo/dmF1bHQ6djE6bEhvR3NUa2dJNzUzOTFYNjd2cnRvRGE0ZUhIRm5MWGM0WGxybllIeDZHVEhpcVZ4KysxWmhVeC8vQWlFLzZZQTdKMjNhUURjUFNZRE5ONWpDczZEK3c9PQ==",
"preferred_username": "rileydoe",
"at_hash": "meToBgo7UfatG825BaaClQ",
"sid": "e10597ce-4b85-4a78-890b-55e2af751c9a",
"aud": "05166b79-4f61-484d-a4b4-2a225926bf4b",
"exp": 1571253248,
"iat": 1571249648,
"iss": "https://www.banno.com/a/consumer/api/oidc"
}
You'll also see a log statement in the terminal that shows the access_token
, id_token
, and refresh_token
:
TokenSet {
access_token: '<lengthy-json-web-token-string>',
expires_at: 1571334444,
id_token: '<lengthy-json-web-token-string>',
refresh_token: '<lengthy-json-web-token-string>',
scope: 'openid address email phone profile offline_access banno',
token_type: 'Bearer'
}
The access_token
contains authorization information about your application regarding which actions it is allowed to perform via the Banno API. These actions map to the scopes (e.g. openid address email phone profile banno
).
The id_token
contains authentication information about the user (i.e. claims).
The refresh_token
is a credential that can be used to retrieve a new access token (e.g. for when the access token has expired or otherwise been invalidated).
Both the access_token
and id_token
are in JSON Web Token format (see RFC 7519 for specification details).
JWTs are credentials which can grant access to resources. It is important to keep them secret.
This project has an example of how to handle deeplinking to a specific page where access is protected behind OpenID Connect authentication. The technique is adapted from https://auth0.com/docs/protocols/oauth2/redirect-users.
The example of how to handle deeplinking is shown in the '/hello'
route within server.js
.
If a user visits http://localhost:8080/hello and is already authenticated, then they will be shown a page which displays their name (e.g. Riley Doe).
Hello Riley Doe
If a user visits http://localhost:8080/hello but is not yet authenticated, then they will be redirected to login at http://localhost:8080/login.html?returnPath=/hello.
A state
is calculated and associated with the returnPath
(in this case, /hello
).
Once the user is authenticated, the state
parameter is compared to the local state
and if it matches then the user is redirected to the associated returnPath
(in this case, /hello
).
An example of how to retrieve Accounts and Transactions for a user is shown in the '/accountsAndTransactions'
route within server.js
.
If a user visits http://localhost:8080/accountsAndTransactions and authenticates, the server will retrieve the Accounts and Transactions for the user and 'pretty print' the data to the page.
-
The server makes an API call to
PUT /a/consumer/api/v0/users/{userId}/fetch
. The response contains an object with ataskId
property. -
The server then makes API calls to
GET /a/consumer/api/v0/users/{userId}/tasks/{taskId}
and polls until an event type ofTaskEnded
is found. (The amount of time this takes is variable based on the number of accounts a user has as well as the hardware the Financial Institution uses for its Core System.) -
After polling is completed, the server makes API calls to
GET /a/consumer/api/v0/users/{userId}/accounts
andGET /a/consumer/api/v0/users/{userId}/accounts/{accountId}/transactions
. -
Finally, the collected data is 'pretty printed' to the page returned to the user.