Skip to main content
Skip table of contents

Obtain Authorization via Open Banking Access

Introduction

To work with permanent users, they must be created and logged in directly in finAPI OpenBanking Access. This requires 2 types of logins, which should be known.

On the one hand, a login as a client is needed to create new users and on the other hand, the login of the user itself is important.

Please note: If users are managed directly in finAPI Open Banking Access, they must also be deleted by the client if the user is no longer needed.
This also means, that before it is deleted in finAPI Open Banking Access, it must be deleted in all Data Intelligence systems where it was used.

For one-time users, we therefore recommend the use of the User Management of the Process Controller, as the administration of users is automated there.

To learn how to self-manage users, we offer the Getting Started - User Management page.

Prerequisites

The major prerequisite is to have a valid set of client credentials: client_id and client_secret.

TL:TR

Used Endpoints

In short, you need to call those 2 endpoints on the finAPI Open Banking Access to obtain a token.

Description

HTTP Method

Process Controller Endpoint

Link to API Doc

Get tokens

POST

/api/v2/oauth/token

https://docs.finapi.io/?product=access#post-/api/v2/oauth/token

Process Overview

cURL Example

Translated into cURL it looks like the following:

Step 1 - Login (cURL)

Log in with client or user credentials with the Content-Type header application/x-www-form-urlencoded.

  • Log in as a client requires grant_type=client_credentials and no username and password fields

  • Log in as a user requires grant_type=client_credentials and username and password of the user have to be provided

Login as client example request:

BASH
curl --location 'https://sandbox.finapi.io/api/v2/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=<your client id>' \
--data-urlencode 'client_secret=<your client secret>' \
--data-urlencode 'grant_type=client_credentials'

Login as user example request:

BASH
curl --location 'https://sandbox.finapi.io/api/v2/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=<your client id>' \
--data-urlencode 'client_secret=<your client secret>' \
--data-urlencode 'username=<username>' \
--data-urlencode 'password=<user password>' \
--data-urlencode 'grant_type=password'

The result looks like this:

JSON
{
   "access_token": "yvMbx_TgwdYE0hgOVb8N4ZOvxOukqfjzYOGRZcJiCjQuRGkVIBfjjV3YG4zKTGiY2aPn2cQTGaQOT8uo5uo7_QOXts1s5UBSVuRHc6a8X30RrGBTyqV9h26SUHcZPNbZ",
   "token_type": "bearer",
   "refresh_token": "0b9KjiBVlZLz7a4HshSAIcFuscStiXT1VzT5mgNYwCQ_dWctTDsaIjedAhD1LpsOFJ7x6K8Emf8M3VOQkwNFR9FHijALYSQw2UeRwAC2MvrOKwfF1dHmOq5VEVYEaGf6",
   "expires_in": 3600,
   "scope": "all"
}

 

Implementation Guide

See a full working project here: finAPI Data Intelligence Product Platform Examples (Bitbucket)
Code from this guide can be found here: Authentication with Open Banking Access OAuth (Bitbucket)
Environment overview can be found here: Environments

The guidelines and the example project are written in Kotlin with Spring Boot. But it is easily adoptable for other languages and frameworks.
For the HTTP connection, we are using here plain Java HttpClient, to be not restrictive for the client selection and that everything is transparent.

Only the actual functionality is discussed in this guideline. Used helper classes or the models can be looked up in the source code.

However, we always recommend using a generated client from our API, which reduces the effort of creating models and functions to access the endpoints and eliminates potential sources of error.

To learn how to generate and apply the API client using the Process Controller "Create user and exchange with access_token" as an example, please see the Getting Started - Code Generator (SDK) Integration.

Please also note that the code presented here and also the repository is only an illustration of a possible implementation. Therefore, the code is kept very simple and should not be used 1:1 in a production environment.

Step 1 - Login

To access services, an access token is required. This token can be checked by the application and is associated with a user or client.

We distinguish between a client access token and a user access token.

A client access token can only be used for administrative purposes, while a user access token is used for business access to the endpoints.

To gain access to a token, the client must first authenticate to an OAuth endpoint. finAPI uses always the Direct access grant flow.

The credentials are transmitted in a POST request to the finAPI Open Banking Access endpoint /api/v2/oauth/token, but the credentials are not transmitted as a body, but as a query parameter together with the Content-Type header application/x-www-form-urlencoded.

A client token is always requested with the parameter grant_type=client_credentials and without username and password, while a user token is requested with grant_type=password and the two parameters.

All query fields are transferred urlencoded.

For more information have a look at our Access API Documentation

Field

Type

Mandatory

clientId

The finAPI clientId of your client. This is required to authenticate the mandator and the client, and as well to create the users behind the process token.

yes

clientSecret

The finAPI clientSecret of your client. This is required to authenticate the mandator and the client, and as well to create the users behind the process token.

yes

grant_type

Defines which grant type should be used.

  • client_credentials is to login as client without username and password

  • password is to login as user with username and password field required

yes

username

The username (id) of the user. Only required, if grant_type=password.

if grant_type=password

password

The password of the user. Only required, if grant_type=password.

if grant_type=password

First, we create a class that will handle the login.
The constructor of the class receives the URL of finAPI Open Banking Access, as well as the client credentials.
We also need an object mapper to easily map the JSON data into objects. The models used can be found in Bitbucket.

For the request, we first create a parameter list (requestQuery), that links the query parameters with &.

Please note that the Content-Type header is set to x-www-form-urlencoded and the parameters are not transferred in the body but as query parameters.

KOTLIN
@Component
class OAuthAuthorization(
    @Value("\${finapi.instances.openbanking.url}") private val openBankingUrl: String,
    @Value("\${finapi.security.credentials.clientId}") private val clientId: String,
    @Value("\${finapi.security.credentials.clientSecret}") private val clientSecret: String,
    private val objectMapper: ObjectMapper
) {
    /**
     * Create a HttpRequest with configured URLs and required headers for the login.
     */
    private fun createLoginRequest(
        username: String? = null,
        password: String? = null
    ): HttpRequest {
        // create query parameters with grant_type and credentials
        val requestQuery = StringBuilder()
        requestQuery.append("client_id=${clientId}")
        requestQuery.append("&client_secret=${clientSecret}")

        // is username and password are set, we want to do a user login, else we are using
        // client_credentials only for client login
        if (username != null && password != null) {
            // if a user is present, we use the grant_type password
            requestQuery.append("&username=${username}")
            requestQuery.append("&password=${password}")
            requestQuery.append("&grant_type=password")
        } else {
            // else we use client_credentials
            requestQuery.append("&grant_type=client_credentials")
        }

        // create request with uri, header and data
        return HttpRequest.newBuilder()
            // build URL for https://<openBanking>/api/v2/oauth/token
            .uri(URI.create("${openBankingUrl}${URI_OAUTH_TOKEN}"))
            // set Content-Type header to application/json
            .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
            // add the body
            .POST(HttpRequest.BodyPublishers.ofString(requestQuery.toString()))
            .build()
    }

    companion object {
        private val log = KotlinLogging.logger { }
        const val URI_OAUTH_TOKEN = "/api/v2/oauth/token"
    }
}

Now that we can create a request, we need to create a client for communication and send the request.

The result is checked at least for the status code.
If this is ok, we map the JSON into an object and return only the access token in the simple example.

If something went wrong, we’ll throw an exception.

Please note that throwing a simple RuntimeException for a production system is not a good idea. Please use your own exception, which will then be handled correctly in your code.

KOTLIN
@Component
class OAuthAuthorization(
    @Value("\${finapi.instances.openbanking.url}") private val openBankingUrl: String,
    @Value("\${finapi.security.credentials.clientId}") private val clientId: String,
    @Value("\${finapi.security.credentials.clientSecret}") private val clientSecret: String,
    private val objectMapper: ObjectMapper
) {
    @Throws(RuntimeException::class)
    fun obtainToken(
        username: String? = null,
        password: String? = null
    ): String {
        // get an access token with Process Controller
        val client = HttpClient.newBuilder().build()

        // send the request and fetch the response
        val response = client.send(
            createLoginRequest(
                username = username,
                password = password
            ),
            HttpResponse.BodyHandlers.ofString()
        )

        // check for status code is 2xx or log and throw an exception
        StatusCodeCheckUtils.checkStatusCodeAndLogErrorMessage(
            response = response,
            errorMessage = "Unable to login."
        )

        // return the object of the mapped result
        val oauthResponseModel = objectMapper.readValue(response.body(), OAuthResponseModel::class.java)
        return oauthResponseModel.accessToken
    }
    
    [...]
}

The token should now be placed in the SecurityContext, for example, so that clients to the finAPI systems can access it.
It must be ensured that the token can only be accessed by the user to which the token belongs.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.