Digital Toolkit

Authentication (Command Line)

Consumer API > Quickstarts > Authentication (Command Line)

The Consumer API uses OpenID Connect and OAuth 2.0 for authentication.

This Quickstart guides you through making your first OpenID Connect authentication using the command line.

Curl

This example assumes that you have a working familiarity with the curl command line tool.

Not comfortable with curl, the command line, or prefer ready-to-run code? Try our Quickstart on Authentication (Node.js Example) instead.

Want to learn more about Authentication?
See the Authentication topic for more details.

Prerequisites

Before you get started, you’ll need to get these from the back office administrator at your financial institution who has access to Banno People.

  • API Credentials
  • User Account
  • Configured Redirect URI

If the administrator does not know where to do this, they can review the External application configuration article on the Banno Knowledge site.

Understanding Your Development Experience
Are you a financial institution?

If you are a financial institution or working directly with a financial institution, you should work with the back office administrator at your institution to get appropriate access to Banno People.

Are you a fintech or independent developer?

If you are a fintech or other developer working without a financial institution, you are likely using the JackHenry.Dev developer portal. In this case, you will not have access to Banno People, however you will still have the ability to create and configure many aspects of your external application and plugin.

For more information on this, see our troubleshooting page.

API credentials

You’ll need API credentials to exercise the authorization flow. The Banno People administrator at your financial institution can provide you with a client_id and client_secret that you can use to access the Consumer API in your environment.

User account

You’ll need a user account to exercise the authorization flow with a test user.

Configured redirect URI

You’ll need to have a Redirect URI configured by your Banno People administrator. This is where the user’s browser will be redirected after the user has granted authorization.

Secure Redirect URIs

Redirect URIs must use HTTPS except in local development. HTTPS is required for all production redirect URIs to properly secure the connection between your application and our API.

The only exception is for local development. The following is a list of local options which are included in the HTTP allowlist:

  • Host names of localhost or those that end in .local
  • Any address in the IPv4 range of 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16 (which includes http://127.0.0.1)

Software requirements

curl

If you don’t have the curl command line tool installed on your system already, you’ll need to install a version that is appropriate for your operating system.

Concept: Understanding the code_challenge and code_verifier parameters

The Proof Key for Code Exchange extension adds additional security to the OAuth2 authorization code flow. The requesting app creates a secret (code_verifier) and submits a hash of that secret on the initial auth request. The secret itself is then submitted as part of the token exchange and ensures that the server exchanging the token is the same one that requested the authorization code.

Generating correct code_verifier and code_challenge values from the command line is difficult. It’s recommended to use an OAuth client that supports PKCE.

Best Practices for code_verifiers

The code_verifier is an important security mechanism in the OAuth 2.0 Authorization Code flow. We specifically use the code_verifier as part of the Proof Key for Code Exchange (PKCE) to prevent code interception attacks.

Here are some best practices to consider around code_verifier usage:

  • Generate a new, cryptographically random, code_verifier for every authorization request. Never reuse them across requests.
  • After completing the token exchange, clear the code_verifier from your application. Do not persist it.
  • If your authorization flow is interrupted, regenerate the code_verifier rather than reusing.

Generating a code verifier

A client simply needs to generate a random string of characters. The string must be at least 43 bytes long and no more than 128 bytes. It must be composed of only the following characters:

  • English letters A-Z or a-z
  • Numbers 0-9
  • Symbols “-”, “.”, “_” or “~”.

Creating the code challenge

The code challenge is created by generating a SHA-256 byte hash of the code verifier. The result is then base64url-encoded.

Example code verifier and code challenge creation

NodeJS example
const crypto = require('crypto');
const codeVerifier = crypto
  .randomBytes(60)
  .toString('hex')
  .slice(0, 128);
const codeChallenge = crypto
  .createHash('sha256')
  .update(Buffer.from(codeVerifier))
  .digest('base64')
  .replace(/=/g, '')
  .replace(/\+/g, '-')
  .replace(/\//g, '_');

To check your work, use this code_verifier and ensure you get the listed code_challenge:

Valid output
code_verifier=e517c32aee2356891326604e79ad7d358154e124c157d762cbc8896fb13bfbc5d93a335cc27df714a9280e8249cbc3507143b3b7829d3fe9f62b9fce
code_challenge=4lKn4LVhzJzjx_BttEPuMcracgFKVKbTMmSKYAvA24Y

Check your work… Paste in a verifier or press the create button to generate one.

code_verifier:
code_challenge:

Step 1. Get Authorization from the user

Send the user to the authorization URL

The authorization URL will be of the form:

Authorization URL format
https://[CONSUMER_API_ENVIRONMENT]/a/consumer/api/v0/oidc/auth?client_id=[CLIENT_ID]
  &redirect_uri=[REDIRECT_URI]
  &scope=[SCOPES]
  &response_type=code
  &state=[STATE]
  &code_challenge=[CODE_CHALLENGE]
  &code_challenge_method=S256
Authentication Security

When using the OAuth Authorization Code flow, it is highly recommended that you utilize the state and nonce parameters for improved security.

The State Parameter
The state parameter should be used to prevent CSRF attacks. Here's how:

  • When you redirect the user to the authorization endpoint, generate a random, unique, string and pass it as the state.
  • The authorization server will return the exact same state value to your redirect URI after the user successfully authorized your app. Verify that the state value matches the one you sent.
  • If the state does not match, you should abort the authorization flow.
  • The state value should be unguessable and unique.

The Nonce Parameter
The nonce parameter should be used to prevent replay attacks when using an "implicit" grant flow. Here's how:

  • When you redirect the user to the authorization endpoint, generate a random, unique, string and pass it as the nonce.
  • The authorization server will return the exact same state value to your redirect URI after the user successfully authorized your app. Verify that the nonce value matches the one you sent.
  • If the nonce does not match, you should abort the flow because it could be a replay.
  • The nonce value should be unguessable and unique.

Where:

  • CONSUMER_API_ENVIRONMENT is specific to your financial institution and matches with Banno Online for your institution.
    • Example: For the Garden demo institution the CONSUMER_API_ENVIRONMENT would be digital.garden-fi.com.
  • CLIENT_ID is the client_id from your API credentials.
  • REDIRECT_URI is the configured Redirect URI where the user’s browser will be redirected after the user has granted authorization.
  • SCOPES is one or more scopes. The openid scope is required to initiate an OpenID Connect request.
  • STATE is an opaque, non-guessable value generated by the client to prevent Cross-site request forgery (CSRF) attacks. This enables the client to verify the validity of the request.
  • CODE_CHALLENGE is the PKCE code challenge value.

Get the authorization code from the redirect

The redirect URL will be of the form:

Redirect URL format
[REDIRECT_URI]?code=[CODE]&state=[STATE]

Where:

  • REDIRECT_URI is the configured Redirect URI.
  • CODE is an authorization code that can be exchanged for an access token.
  • STATE is the client-generated value passed in to the authorization URL.

Step 2. Exchange the authorization code for an access token

Request using curl

Use curl to make an HTTP POST request of the form:

Curl token post
curl -v --request POST \
  --url https://[CONSUMER_API_ENVIRONMENT]/a/consumer/api/v0/oidc/token \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data client_id=[CLIENT_ID] \
  --data client_secret=[CLIENT_SECRET] \
  --data grant_type=authorization_code \
  --data 'code=[CODE]' \
  --data redirect_uri=[REDIRECT_URI] \
  --data code_verifier=[CODE_VERIFIER]

Where:

  • CONSUMER_API_ENVIRONMENT is specific to your financial institution and matches with Banno Online for your institution.
    • Example: For the Garden demo institution the CONSUMER_API_ENVIRONMENT would be digital.garden-fi.com.
  • CLIENT_ID is the client_id.
  • CLIENT_SECRET is the client_secret from your API credentials.
  • CODE is the authorization code from the previous step.
  • REDIRECT_URI is the configured Redirect URI.
  • CODE_VERIFIER is the PKCE code verifier value.

Authentication response

The authentication server will respond with a JSON payload of the form:

Token Response
{
  "access_token": "<lengthy-json-web-token-string>",
  "expires_in": 3600,
  "id_token": "<lengthy-json-web-token-string>",
  "scope": "openid",
  "token_type": "Bearer"
}

Where:

  • access_token is the access token in JWT (JSON Web Token) format.
  • expires_in is the amount of time (in seconds) for which the access token is valid.
  • id_token is the identity token in JWT (JSON Web Token) format.
  • scope is the set of scopes authorized by the user.
  • token_type is the type of token (the string “Bearer”).

Token formats

The Access Token and Identity Token are encoded in JWT (JSON Web Token) format. When they are decoded, they will look similar to the forms described below.

Access token

The Access Token contains authorization information about your application regarding which actions it is allowed to perform via the Consumer API.

These actions map to the scopes (e.g. openid).

Decoded Access Token
{
  "jti": "_Prnud9uU6S1Gjd_z_x0n",
  "sub": "5cad5c30-6d24-11e9-870c-0242b78f8571",
  "iss": "https://digital.garden-fi.com/a/consumer/api/v0/oidc",
  "iat": 1591056386,
  "exp": 1591059986,
  "scope": "openid",
  "aud": "55fc6a69-a4dd-404c-97f9-e2361b4c44b1"
}

Identity token

The Identity Token contains authentication information about the user (i.e. claims).

Decoded Identity Token
{
  "sub": "5cad5c30-6d24-11e9-870c-0242b78f8571",
  "nonce": "qe8zu0qoi5h",
  "at_hash": "xAaATGqdRxgZ4wiSVSjSPw",
  "sid": "68530fe4-bd6e-412d-bac7-6970aa74fecc",
  "aud": "55fc6a69-a4dd-404c-97f9-e2361b4c44b1",
  "exp": 1591059986,
  "iat": 1591056386,
  "iss": "https://digital.garden-fi.com/a/consumer/api/v0/oidc"
}

See the RFC for more details on Identity Token claims.

The sub (Subject Identifier) claim is of particular importance when using the Consumer API as you’ll use this when the API path includes a {userId} reference.

JSON Web Tokens (JWTs) are credentials which can grant access to resources. It is important to keep them secret.

Next steps

Congratulations! Continue your learning journey:


Have a Question?
Have a how-to question? Seeing a weird error? Get help on StackOverflow.
Register for the Digital Toolkit Meetup where we answer technical Q&A from the audience.
Last updated Wed Nov 8 2023