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.
your-redirect-uri/?code=<authorization_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
Refresh tokens are not static values
Note that refresh tokens change aswell as the access tokens, which makes it very important for you to save both access tokens and refresh tokens on your side, in order to make authorized requests and to refresh tokens in a correct way.
Updated 3 months ago