Server application
Server applications are able to authenticate with the Unimicro APIs through a certificate based client credential flow.
They may act on behalf of companies they've been given access to without human interaction.
This article shows how to authenticate as a C# .NET server client.
Create a client token
In order to create a client token we start by loading our certificate. We then use this certificate to sign a JWT access token with our Client ID and the identity server's token endpoint.
// Audience should be set to the identity server's token endpoint, e.g. https://test-login.unimicro.no/connect/token for our test environment
private static string CreateClientToken(string clientId, string audience)
{
    var certificate = new X509Certificate2(@"path\to\Cert.p12", "certificate password");
    var now = DateTime.UtcNow;
    var securityKey = new X509SecurityKey(certificate);
    var signingCredentials = new SigningCredentials(
        securityKey,
        SecurityAlgorithms.RsaSha256
    );
    var token = new JwtSecurityToken(
        clientId,
        audience,
        new List<Claim>()
        {
            new Claim("jti", Guid.NewGuid().ToString()),
            new Claim(JwtClaimTypes.Subject, clientId),
            new Claim(JwtClaimTypes.IssuedAt, now.ToEpochTime().ToString(), ClaimValueTypes.Integer64)
        },
        now,
        now.AddMinutes(1),
        signingCredentials
    );
    var tokenHandler = new JwtSecurityTokenHandler();
    return tokenHandler.WriteToken(token);
}
 The resulting token should contain the following fields in it's payload.
{
  "jti": <guid>,
  "sub": <clientid>,
  "iat": 1592557940,
  "nbf": 1592557940,
  "exp": 1592558000,
  "iss": <clientid>,
  "aud": "https://test-login.unimicro.no/connect/token"
}
 Request access token
Once you have your client token you can use that to request an access token.
static async Task<TokenResponse> RequestTokenAsync()
{
    var client = new HttpClient();
    var disco = await client.GetDiscoveryDocumentAsync("https://test-login.unimicro.no");
    if (disco.IsError) throw new Exception(disco.Error);
    var clientToken = CreateClientToken("client-id", disco.TokenEndpoint);
    var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
    {
        Address = disco.TokenEndpoint,
        Scope = "Scope1 scope2",
        ClientAssertion =
        {
            Type = OidcConstants.ClientAssertionTypes.JwtBearer,
            Value = clientToken
        }
    });
    if (response.IsError) throw new Exception(response.Error);
    return response;
}
 The request to connect/token that was generated should look something like this.
POST https://test-login.unimicro.no/connect/token
Body (application/x-www-form-urlencoded)
{
    "client_id": "<clientId>",
    "scope": "AppFramework",
    "grant_type": "client_credentials",
    "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
    "client_assertion": "<local generated jwt-token>"
  }
 Send a request to the API
Once you have your access token you can use it to communicate with the Unimicro APIs. Let's fetch the CompanySettings entity.
static async Task CallServiceAsync(string token)
{
    var baseAddress = "https://test.unimicro.no/";
    var client = new HttpClient
    {
        BaseAddress = new Uri(baseAddress)
    };
    client.SetBearerToken(token);
    try
    {
        var response = client.GetStringAsync("https://test.unimicro.no/api/init/companies").Result;
        Console.WriteLine("Result: " + JArray.Parse(response));
        var companies = JsonConvert.DeserializeObject<List<Company>>(response);
        client.DefaultRequestHeaders.Add("CompanyKey", companies[0].Key);
        var companyResponse = client.GetStringAsync("https://test.unimicro.no/api/biz/companysettings").Result;
        Console.WriteLine("CompanySettings: " + JArray.Parse(companyResponse));
    }
    catch (Exception ex)
    {
        Console.WriteLine("Exception: " + ex.Message + " \n stack " + ex.StackTrace);
    }
}
 References
The following references has been used in these examples
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;
using IdentityModel;
using IdentityModel.Client;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using NodaTime;