Authentication

Give me access!

Introduction

Applications connect to Visma eAccounting and Visma Lön Smart API using OAuth2, the standard used by most APIs for authenticating and authorizing users. The following documentation will guide you how to authorize your application to act on behalf of a user (also referred to as the resource owner).

The OAuth2 flow is generally initiated by a user clicking a “Connect with Visma eAccounting/Visma Lön Smart” button in your application (web application, mobile app or desktop application). The end result of the OAuth2 flow is a token your application will use to access protected resources in the API's on behalf of the user. The token is unique to each application/user combination.

Both Visma eAccounting and Visma Lön Smart share the same Identity Server. Therefor the same token can be used towards both API's as long as the required scopes are authenticated.

Scopes

You need to provide a list of requested scopes in the authentication request. API endpoints are related to a scope, eg. sales related endpoints requires the sales scope.

Scope

Access

Description

ea:api
  • required_ (For eAccounting integrations)

Must be used to get access to eAccounting API

offline_access

required

Must be used to be able to receive a refresh token

ea:sales

optional

Full access to sales resources

ea:sales_readonly

optional

Read-only access to sales resources

ea:accounting

optional

Full access to accounting resources

ea:accounting_readonly

optional

Read-only access to accounting resources

ea:purchase

optional

Full access to purchase resources

ea:purchase_readonly

optional

Read-only access to purchase resources

vls:api
  • required_ (For Lön Smart integrations)

Must be used to get access to Lön Smart API

The Server-side Flow

1. User Authentication

When the user clicks a “Connect with Visma eAccounting/Visma Lön Smart” button in your application, your application should make a request towards our authorization endpoint. In that request you need to provide client id, redirect uri, scopes, state, response type and the login prompt.

Parameter Name

Required

Description

client_id

required

Provided to you upon registration for the Visma Partner Programme

redirect_uri

required

Callback uri that you have registered upon registration for the Visma Partner Programme

scope

required

Permissions to request, see below for more information. If passing multiple scopes, separate them using %20 (URL-encoded space character) or + character

response_type

required

The grant type requested, for server-side flow it is always code

state

recommended

A unique string that is passed back upon completion. It should be used to avoid cross-site forgery attacks by passing in a value that’s unique to the user you’re authenticating and checking it when authorize completes

prompt

recommended

Set select_account to ignore the standard company setting in Visma Online and always prompt the user with the selection of company. This is highly recommended.

Set prompt=login to force user login.

These two prompt values can be used in combination with a + sign as a separator. The query will then look like this: prompt=login+select_account

acr_values

recommended

Set acr_values=service:44643EB1-3F76-4C1C-A672-402AE8085934 to show only the companies that have access to eAccounting in the company selector.

## Example on how the authentication request can look like

curl -X GET 'https://identity.vismaonline.com/connect/authorize?client_id=<client_id>&redirect_uri=<redirect_uri>&scope=ea:api%20offline_access%20ea:sales&state=<state_string>&response_type=code&prompt=select_account&acr_values=service:44643EB1-3F76-4C1C-A672-402AE8085934'

2. App Authorization & Redirect

Once Visma Authorization Server has successfully authenticated the user, the server will prompt them to authorize the application.

If the user clicks “Allow”, your application will be authorized. The Visma Authorization Server will redirect the user’s browser via HTTP 302 to the redirect_uri with an authorization code.

The authorization code is one time use and is valid for 5 minutes, in order to exchange it for access token and refresh token, which will be explained in the next section.

<code>your-redirect-uri/?code=<authorization_code></code>

3. App Authentication

When you have recieved the authorization code, next step is to exchange that for a set of tokens. These tokens are needed in order to make authorized requests towards the authenticated company.

Issue a post request like the example below. Note that the Authorization header in this request is client_id followed by a punctiuation sign : followed by client_secret. Then Base64 encode that string and provide, like in the example.

POST /connect/token HTTP/1.1
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded;charset=UTF-8

"grant_type=authorization_code&code=<authorization_code>&redirect_uri=<redirect_uri>"
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8

{
  "access_token": <access_token>,
  "refresh_token": <refresh_token>,
  "token_type":"bearer",
  "expires_in":3600
}

We recommend that you save all information in the response on your side, in order to make your integration as smooth as possible.

4. Using The Access Token

The access token is your way in to the API, and must be provided in all requests to the API. Since it's a bearer type of token, it should be provided as one aswell.

## This is a authorized request towards the API. The token is faked in this example.

curl -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSIsImtpZCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSJ9.eyJpc3MiOiJodHRwczovL2lkZW50aXR5LnZpc21hb25saW5lLmNvbSIsImF1ZCI6Imh0dHBzOi8vaWRlbnRpdHkudmlzbWFvbmxpbmUuY29tL3Jlc291cmNlcyIsImV4cCI6MTUwNzg4OTE5MiwibmJmIjoxNTA3ODg1NTkyLCJjbGllbnRfaWQiOiJjb2RlY2xpZW50Iiwic2NvcGUiOlsiZWE6c2FsZXMiLCJlYTpwdXJjaGFzZSIsImVhOmFjY291bnRpbmciLCJvZmZsaW5lX2FjY2VzcyIsImVhOmFwaSJdLCJzdWIiOiI2NjVhYzU5Yy0yNThiLTQzM2UtODA2Zi02MzkxZjU1MmFhOGEiLCJhdXRoX3RpbWUiOjE1MDc4ODU1NTQsImlkcCI6InZvbmlkc3J2IiwiY3VzdG9tZXJfaWQiOiI4ZDZhODZmZS1mN2IzLTRhZmUtOWQ5Mi1mNzY5OGJiMTJhZjAiLCJlbWFpbCI6ImFkbWluQHZpc21hb25saW5lLnNlIiwiYW1yIjpbImV4dGVybmFsIl19.LIIRPjwtDEtCYD1Sz2jlKDX9MClLDDXYSyfhjPKyGxOfXzBzfgNHfFmp6fa9AZ7RJZ9QFtbQ0vFj_QJgsWia6jJp_-is1LX_1cqB9G3XxbOuzJuIAVtd9gRgT16OVJ_vmwnll2mF2HD0XcYkJ5oppogF9CGJ3LY-stC8HaPkrW8eYEQ5vrJJjhC7RExVW_HXWRnb_mams7bK3lx2odFzCRglHXMNOgSgnbW0oOWRPCmWoP5_RY59t_9xB3GQ5hFQ5IxvVITJomr_uSk8iqF1m3aJn5oGfXjxH-63-0tVXEbnBtci-n15VG3K-Wh2Wbo_OWe434N9Euz-uXMJSCPgDg" \
'https://eaccountingapi.vismaonline.com/v2/companysettings'

60 minutes after the Access Token was issued, it will expire. In the next section we will go through how to refresh it using the refresh token.

5. Using The Refresh Token

When the Access Token has expired, it's time to make sure you have a new before next request in order to prevent unauthorized requests.

The request needed in this case is quite similar to the app authentication request but with a few modifications.

Change grant_type value to refresh_token. Also provide a property called refresh_token instead of code. The value of the refresh_token property is the refresh token itself. The response properties are identical to the previous request.

POST /connect/token HTTP/1.1
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded;charset=UTF-8

"grant_type=refresh_token&refresh_token=<refresh_token>"
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8

{
  "access_token": <access_token>,
  "refresh_token": <refresh_token>,
  "token_type":"bearer",
  "expires_in":3600
}

6. Token Revocation

If you would like to revoke a issued Refresh Token, you can use the Revocation endpoint. The provided Token will be invalidated for further use.

The Authorization towards this enpoint is the same as in the App Authentication request, client_id followed by a punctiuation sign : followed by client_secret. Then Base64 encode that string and provide in the request.

The request body contains two properties, token and token_type_hint. Token is required, but token_type_hint isn't. If token_type_hint isn't provided, the IdentityServer will try to figure out if it's a Access Token or Refresh Token. In the example below, I choose to let the IdentityServer know that it's a Refresh Token I would like to revoke.

POST /connect/revocation HTTP/1.1
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded;charset=UTF-8

"token=<refresh_token>&token_type_hint=refresh_token"

If successful, you will get a blank response with status code 200 OK.

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8