Web applications/businessnxtapi/authentication/websectionLearn how to set up web applications for integrating with Business NXT, including OAuth authorization essentials.2024-09-24T15:57:29+02:00
# Web applications
Learn how to set up web applications for integrating with Business NXT, including OAuth authorization essentials.
For integrating with Business NXT, you can choose one of these two type of applications:
- Service: suitable for web services that require a machine-to-machine integration (with no user interation).
- Web: suitable for web applications that require user interaction.
In this section, you will learn about the setup required for web applications.
> [!TIP]
>
> If you are not familiar with the OAuth authorization flows, we recommend that you first read carefully the page [Understanding OAuth](../oauth.md) to familiarize yourself with concepts such as authentication and authorization, access tokens, scopes, grants, endpoints and redirect URLs. You need to have a basic understanding of these concepts in order to properly register your application and setup an integration with Business NXT GraphQL API.
Application registration/businessnxtapi/authentication/web/setup_webpageLearn how to register a web application on Visma Developer Portal to integrate with Business NXT GraphQL API.2024-09-24T15:57:29+02:00
# Application registration
Learn how to register a web application on Visma Developer Portal to integrate with Business NXT GraphQL API.
In order to integrate with Business NXT you must register an application in the Visma Developer Portal and add an integration to Business NXT GraphQL. Here, you will learn how to do this. This section describes how to register a web application.
> [TIP]
>
> If you are not familiar with the OAuth authorization flows, we recommend that you first read carefully the page [Understanding OAuth](../oauth.md) to familiarize yourself with concepts such as authentication and authorization, access tokens, scopes, grants, endpoints and redirect URLs. You need to have a basic understanding of these concepts in order to properly register your application and setup an integration with Business NXT GraphQL API.
You must follow these steps:
1. Logon to [Visma Developer Portal](https://oauth.developers.visma.com).
2. From the menu, select My **Applications** and then press the **Add applications** button.

3. Select the **Web** application type.

4. Fill in the registration form. You must select an application name, a unique client identifier, a description of your application, as well as URLs for the authentication workflow. From this form, you can customize application policies and branding. When completed, you must press the **Save as draft** button and then **Send for approval**.

5. Your application must be approve by Visma before you can start using it. Before approval, it will display the *Pending approval* status.

After the approval process complete, you can add integrations to your application. See [GraphQL API integration](integrations_web.md) to learn how to do that.
## Application Credentials
If you plan to use an web application with client credentials (performing the OAuth flow using the client credentials grant type), this requires both a *client ID* and a *client secret*. In this case, you also need to generate a client secret.
Secrets can be generated and deleted from the **Credentials** tab in Visma Developer Portal.

> [!NOTE]
>
> A secret is only visible when it is generated after which you can no longer read it. You must copy and preserve it in a secure place.
## Local App Development
For the development of your application on local machines, you must register a local URL for login and redirect. The use of `localhost` is not supported in the Visma Developer Portal but `app.local` can be used instead. Assuming your application runs locally on the 12345 port, use the following configuration:
```
Initiate Login URI: https://app.local:12345/
Frontchannel Logout URI: https://app.local:12345/logout
Redirect URIs: https://app.local:12345/signin-oidc
```GraphQL API integration/businessnxtapi/authentication/web/integrations_webpageStep-by-step guide to integrate a web application with Business NXT GraphQL API and initiate the OAuth flow for creating tokens2024-09-24T15:57:29+02:00
# GraphQL API integration
Step-by-step guide to integrate a web application with Business NXT GraphQL API and initiate the OAuth flow for creating tokens
After the approval of the registration of your web application, you can add integrations to Visma APIs. To integrate with Business NXT GraphQL API do the following:
1. Select your application from the **My Applications** main tab and go to **Integrations**.

2. Press the **New integration** button.
3. Search and select the **Business NXT Graphql API** in the combo with available APIs and press **Continue**.

If you plan to use the client credentials grant type, then you need search for **Business NXT GraphQL API** in the combo with available APIs and press **Continue**.

4. Select the `business-graphql-api:access-group-based` scope (or `business-graphql-service-api:access-group-based` if you seleced **Business NXT Graphql Service API** in the previous step) and press **Continue**.

5. Review the selection and confirm the integration by pressing the **Confirm Integration** button.

6. Wait for the integration to be approved by Visma.

Once approved, the integrations become active.

Once your application is integrated with **Business NXT Graphql API**, you can initiate the OAuth flow and create tokens.
The minimum required claims for a valid OAuth 2.0 JWT token are:
```text
Default OAuth 2.0 Claim required:
sub
Scope Claims required:
email
openid
business-graphql-api:access-group-based
```
Company access is determined by the corresponding user for whom the OAuth JWT token was created. The rights for the user are managed in Visma.net.Setting up user nightly jobs with unattended access/businessnxtapi/authentication/web/unattendedaccesspageGuide to setting up unattended nightly jobs using OIDC refresh tokens for data import from Business NXT in web applications.2024-09-24T15:57:29+02:00
# Setting up user nightly jobs with unattended access
Guide to setting up unattended nightly jobs using OIDC refresh tokens for data import from Business NXT in web applications.
When using a web application, setting up a nightly job for importing data from Business NXT can be done with the help of OIDC *refresh tokens*.
> [!TIP]
>
> For this kind of scenario, the best approach is to use a service application. To learn more about this see [Services](/businessnxtapi/authentication/service/).
Only web applications in the Visma Developer Portal can have a refresh token and they require an OIDC-enabled backend to store the refresh token. You will also need to include the `offline_access` scope for the application.
After checking offline access, you will gain access to more settings related to the refresh token:

You can create a **job user** in Visma.net and assign its correct privileges to certain companies and company groups. It can even be your currently logged in user under which the job will run. After loging in with the user under which the unattended job will run, you will need to store this refresh token to refresh tokens and use it after the regular tokens expire, without requiring the user (that the nightly job will run under) to login again.
> [!TIP]
>
> See more information about refresh tokens in the [Visma Developer Portal documentation](https://oauth.developers.visma.com/service-registry/documentation/authentication#offlineAccess).
Examples for setting up authorization/businessnxtapi/authentication/web/examplessectionHere you can find some examples for how to set up authorization.2024-09-24T15:57:29+02:00
# Examples for setting up authorization
Here you can find some examples for how to set up authorization.
Click the links below to look at examples for how to set up authorization for either .NET, Postman, or Insomnia.
.NET Code Sample/businessnxtapi/authentication/web/examples/codepage.NET sample app for integrating with Business NXT using OAuth flow. Clone or create ASP.NET app, setup configs, run to authenticate.2024-09-24T15:57:29+02:00
# .NET Code Sample
.NET sample app for integrating with Business NXT using OAuth flow. Clone or create ASP.NET app, setup configs, run to authenticate.
If you're using .NET (3.1/5/6) to build your application that integrates with Business NXT, you can set it up as described below to perform the oauth flow.
> [!NOTE]
>
> The code for the application described here is available on GitHub at [GraphQLSamples/MvcCode](https://github.com/Visma-Business/GraphQLSamples/tree/main/MvcCode).
>
> This application is a modified version of the [MvcCode sample](https://github.com/IdentityServer/IdentityServer4/tree/main/samples/Clients/src/MvcCode) from the [IdentityServer](https://github.com/IdentityServer) project.
## Getting started
You can either clone the MvcCode sample repository or create an Asp.Net application from scratch. The sample application described here has the following structure:

## Application setup
The `Program.cs` source file has the following content:
```
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace MvcCode
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup();
});
}
}
```
The `Setup.cs` source file contains the following:
```
using IdentityModel;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using IdentityModel.Client;
using Microsoft.IdentityModel.Logging;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
namespace MvcCode
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddControllersWithViews();
services.AddHttpClient();
services.AddOptions();
services.Configure(Configuration);
services.AddSingleton(r =>
{
var factory = r.GetRequiredService();
return new DiscoveryCache(Configuration.GetValue("Authority"),
() => factory.CreateClient());
});
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddCookie(options =>
{
options.Cookie.Name = "mvccode";
})
.AddOpenIdConnect("oidc", options =>
{
options.Events.OnTokenResponseReceived = (tokenResponse) =>
{
var accessToken = tokenResponse.TokenEndpointResponse.AccessToken;
return Task.CompletedTask;
};
options.Events.OnRemoteFailure = (err) =>
{
return Task.CompletedTask;
};
options.Events.OnMessageReceived = (msg) =>
{
return Task.CompletedTask;
};
options.Authority = Configuration.GetValue("Authority");
options.RequireHttpsMetadata = false;
options.ClientId = Configuration.GetValue("ClientId");
options.ClientSecret = Configuration.GetValue("ClientSecret");
options.ResponseType = "code id_token";
options.UsePkce = true;
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("business-graphql-api:access-group-based");
options.Scope.Add("offline_access");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.Name,
RoleClaimType = JwtClaimTypes.Role,
};
});
}
public void Configure(IApplicationBuilder app)
{
IdentityModelEventSource.ShowPII = true;
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute()
.RequireAuthorization();
});
}
}
}
```
From this snippet, you should notice the following:
- Authority, client ID, and client secret are read from the application settings.
- The response type is `code id_token`.
- The requested scopes are `openid`, `profile`, `email`, `business-graphql-api:access-group-based`, and `offline_access`. The latter is only needed when offline access is required.
## Application Settings
The JSON file with the application settings (`appsettings.json`) looks as follows:
```
{
"ClientId": "...",
"ClientSecret": "...",
"Authority": "https://connect.visma.com",
"SampleApi": "https://localhost:5005/"
}
```
The client ID is the one you specified when you registered your application with the Visma Developer Portal. The client secret is a value generated in the **Credentials** tab of the application propertys in the Visma Developer Portal.
> [!NOTE]
>
> Make sure you do not upload the content of this file to a public repository such as on GitHub.
The `AppSettings.cs` file contains the following class definition used to help with accessing the settings:
```
namespace MvcCode
{
public class AppSettings
{
public string ClientId { get; set; }
public string ClientSecret { get; set; }
public string Authority { get; set; }
public string SampleApi { get; set; }
}
}
```
## Controllers
The `HomeController` class is implemented as follows:
```
using System;
using System.Globalization;
using System.Net.Http;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
namespace MvcCode.Controllers
{
public class HomeController : Controller
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly IDiscoveryCache _discoveryCache;
private readonly AppSettings _authSettings;
public HomeController(IHttpClientFactory httpClientFactory, IDiscoveryCache discoveryCache, IOptions authSettings)
{
_httpClientFactory = httpClientFactory;
_discoveryCache = discoveryCache;
_authSettings = authSettings.Value;
}
[AllowAnonymous]
public IActionResult Index() => View();
public IActionResult Secure() => View();
public IActionResult Logout() => SignOut("oidc");
public async Task CallApi()
{
var token = await HttpContext.GetTokenAsync("access_token");
var client = _httpClientFactory.CreateClient();
client.SetBearerToken(token);
var response = await client.GetStringAsync(_authSettings.SampleApi + "identity");
ViewBag.Json = JArray.Parse(response).ToString();
return View();
}
public async Task RenewTokens()
{
var disco = await _discoveryCache.GetAsync();
if (disco.IsError) throw new Exception(disco.Error);
var rt = await HttpContext.GetTokenAsync("refresh_token");
var tokenClient = _httpClientFactory.CreateClient();
var tokenResult = await tokenClient.RequestRefreshTokenAsync(new RefreshTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = _authSettings.ClientId,
ClientSecret = _authSettings.ClientSecret,
RefreshToken = rt
});
if (!tokenResult.IsError)
{
var oldIdToken = await HttpContext.GetTokenAsync("id_token");
var newAccessToken = tokenResult.AccessToken;
var newRefreshToken = tokenResult.RefreshToken;
var expiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(tokenResult.ExpiresIn);
var info = await HttpContext.AuthenticateAsync("Cookies");
info.Properties.UpdateTokenValue("refresh_token", newRefreshToken);
info.Properties.UpdateTokenValue("access_token", newAccessToken);
info.Properties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture));
await HttpContext.SignInAsync("Cookies", info.Principal, info.Properties);
return Redirect("~/Home/Secure");
}
ViewData["Error"] = tokenResult.Error;
return View("Error");
}
}
}
```
In this snippet:
- `CallApi()` is a function that makes an HTTP request to (or whatever base URL is specified in the `SampleApi` property in the application settings).
- `RenewTokens()` is a function that runs the oauth flow to refesh the access token.
## Views
The view files are as follows:
- `Index.cshtml`
```
@{
ViewData["Title"] = "Home Page";
}
```
## Running the Application
When you run the application (for instance on port 44303 at or ) you get the following welcome page:

When you click on **Secure** you are redirected to Visma Connect for authentication:

After completing the authentication, the **Secure** page lists your user identity claims:

You can also find, on the same page, the authentication properties, such as the ID token, the access token, and the refresh token:

Postman/businessnxtapi/authentication/web/examples/postmanpageConfigure Postman authorization using Bearer tokens per request or collection. Learn more in the official Postman documentation.2025-06-13T15:38:13+02:00
# Postman
Configure Postman authorization using Bearer tokens per request or collection. Learn more in the official Postman documentation.
In Postman, you can set the authorization method and details either per request or collection.
You must use the **Bearer token** authorization type and specify an access token. You can fetch an access token in different ways. A possible way is using the [.NET sample application](code.md).

> [!TIP]
>
> You can learn more about about authentication in Postman from its official documentation. See [Authorizing requests](https://learning.postman.com/docs/sending-requests/authorization/).
Insomnia/businessnxtapi/authentication/web/examples/insomniapageSet up Insomnia with Bearer Token authorization, fetch access tokens via .NET application, and learn more about authentication techniques.2025-06-13T15:38:13+02:00
# Insomnia
Set up Insomnia with Bearer Token authorization, fetch access tokens via .NET application, and learn more about authentication techniques.
In Insomnia, you can set the authorization method and details per request.
You must use the **Bearer Token** authorization type and specify an access token. You can fetch an access token in different ways. A possible way is using the [.NET sample application](code.md).

> [!TIP]
>
> You can read more about authentication in the [Insomnia docs](https://docs.insomnia.rest/insomnia/authentication).