Sist endret: 10. nov. 2024

Integrasjon av Altinn-app med Maskinporten

Hvordan sette opp en integrasjon mellom en Altinn-app og Maskinporten.

Dette er en guide om hvordan du setter opp en Altinn-applikasjon for å opprette en klient som bruker en Maskinporten-integrasjon for sine forespørsler. Dette er relevant når applikasjonen skal utføre forespørsler som må autentiseres på vegne av organisasjonen som eier applikasjonen, og ikke sluttbrukeren som eier instansen. Av naturen, vil disse forespørslene ha legitimasjon fra den private brukeren som logget på applikasjonen og opprettet den nye instansen. For å sende disse forespørslene på vegne av organisasjonen, må følgende gjøres;

  1. Forsikre deg om at organisasjonen har tilgang til Azure Key Vault.
  2. Opprett integrasjonen til Maskinporten på Samarbeidsportalen.
  3. Lagre nøklene fra integrasjonen i Azure Key Vault for organisasjonen.
  4. Sett opp applikasjonen til å bruke Maskinporten-klienten ved å hente hemmelighetene/nøklene fra Azure Key Vault.

Tilgang til Azure Key Vault

Før du går videre i denne guiden, må du sørge for at du har tilgang til Azure Key Vault for organisasjonen din, slik at nøklene som opprettes senere i guiden, kan legges direkte inn i hemmelighetene i Azure.

Hvis tilgang mangler, se Tilgang til logger og hemmeligheter.

Maskinporten-integrasjon

I denne delen blir Maskinporten-klienten satt opp. En del av oppsettet av klienten inkluderer opprettelse av nøkler som skal lagres i Azure Key Vault senere i guiden. Hvis ulike personer i organisasjonen har tilgang til forskjellige ressurser som trengs i denne prosessen, samarbeid og gjør de følgende trinnene på samme maskin. Dette er anbefalt for å unngå å sende hemmeligheter mellom maskiner.

Når tilgang til å opprette hemmeligheter i Azure Key Vault er bekreftet, kan du fortsette med å opprette integrasjonen.

Prerequisites

Register new integration through Samarbeidsportalen

  • Login to Samarbeidsportalen in Test or Production

  • Choose Selvbetjening and then Integrasjoner for the environment you want. Ver2 is test and Produksjon is production.

    “Samarbeidsportalen”
    Samarbeidsportalen

  • Choose Ny integrasjon

    “New integration”
    New integration

  • To fill out the form, provide all required properties:

    • Scopes: Choose Legge til scopes and include all the scopes necessary for the integration to generate tokens containing
    • Navn på integrasjonen: Add a descriptive name that allows you to identify the application that will be using the integration
    • Beskrivelse: Add a short description, not only for yourself but for everyone that administers integrations on behalf of your organization.

    “Add values for integration”
    Add values for integration

    The example above shows an integration used by an Altinn CLI Client which will need to generate tokens containing one or more of the three selected scopes; altinn:serviceowner, altinn:serviceowner/instances.read and altinn:serviceowner/instances.write

  • Choose Opprett in the top right corner when you have completed the configuration

The final steps of this guide cover creating a Json Web Key (JWK) for the integration to use to authenticate towards maskinporten, as well as noting down important values that can be used to configure the client that will integrate with Maskinporten.

Generate and register JWK for authentication towards Maskinporten

To avoid spreading the business certificate across many systems, we opt for creating an asymmetric key (JSON Web Key) and associate it to the newly created integration. In this example we use mkjwk.org.

  • Navigate to mkjwk.org in a browser

  • Fill in values like the example below and click Generate

    “New JWK”
    New JWK

    The output should look like this:

    “The JWK”
    The JWK

Now, the public part of the key should be added to the newly created integration in Samarbeidsportalen.

  • Navigate back to the integration in Samarbeidsportalen

  • Choose Egne public nøkler

    “Own public keys”
    Own public keys

  • Add two empty square bracets to the empty text box as shown below

    “Add array”
    Add array

  • Navigate back to the JWK generator site

    “The JWK”
    The JWK

  • Copy the public key of the JWK (marked 1 in the picture) and paste this into the array in Samarbeidsportalen.

    “Add public key”
    Add public key

  • Choose Legg til

The registration and configuration in Samarbeidsportalen is now complete, and the integration is ready to generate Maskinporten tokens on request from any client that can provide the private and public parts of the JWK.

Important values for client configuration

From samarbeidsportalen:

  • Integrasjonens identifikator

    This will be used in your client configuration. In Altinn libraries, this value is referred to as the client identifikator

From the JWK generation tool:

  • Public and private key pair (marked 2 in the picture below) This is what your client will use when calling the Maskinporten integration.

    “The JWK”
    The JWK

In Altinn libraries this key pair is referenced as EncodedJwk and must be base64 encoded before it is included in application configuration or uploaded to a Key Vault.

Base64encode.org can be used for encoding.

Konfigurasjon av Azure Key Vault

Når applikasjonen forberedes på å bruke hemmelighetene fra Azure Key Vault, er det noen trinn som må gjøres:

  1. Legg til hemmelighetene hentet under konfigurasjonen av Maskinporten-klienten i Azure Key Vault:

    • Base64-kodet JWT offentlig og privat nøkkelpar
    • Klient-ID for integrasjonen

    Det er viktig at navnet på disse hemmelighetene i Azure Key Vault samsvarer med navnet på seksjonen i appsettings-filen i applikasjonsrepositoryet. For eksempel, hvis appsettings-seksjonen for Maskinporten-integrasjonen ser slik ut:

    {
      "MaskinportenSettings": {
        "Environment": "ver2",
        "ClientId": "",
        "Scope": "altinn:serviceowner/instances.read",
        "EncodedJwk": "",
        "ExhangeToAltinnToken": true,
        "EnableDebugLog": true
      }
    }
    

    Hemmelighetene i Azure Key Vault burde ha navn som dette:

    MaskinportenSettings--ClientId
    MaskinportenSettings--EncodedJwk
    
  2. For at applikasjonen skal kunne lese hemmelighetene fra Azure Key Vault, må applikasjonen konfigureres til å gjøre dette. Se seksjoner om hemmeligheter for å oppnå dette.

  3. Legg til eksempel på appsettings-seksjonen ovenfor i appsettings.{env}.json-filen.

NB: Hemmelighetene leses av applikasjonen ved oppstart, så hvis du endrer hemmelighetene etter at applikasjonen er publisert, må du deploye applikasjonen på nytt.

Sett opp applikasjonen til å bruke Maskinporten-integrasjonen

Når du endrer applikasjonen for å bruke Maskinporten-integrasjonen, må vi tilpasse filen Program.cs.

For det første må vi legge til tjenesten MaskinportenHttpClient med riktig konfigurasjon i funksjonen RegisterCustomAppServices:

services.AddMaskinportenHttpClient<SettingsJwkClientDefinition, AppClient>(config.GetSection("MaskinportenSettings"));

Deretter må vi legge til Azure Key Vault sin configuration provider til koden vår. Da trenger vi disse pakkereferansene i prosjektfila (App.csproj) - husk å velge siste versjoner fra NuGet.org:

<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.1" />
<PackageReference Include="Azure.Identity" Version="1.11.4" />

Så kan vi konfigurere opp Azure Key Vault configuration provider:

using Azure.Identity;

// ...

void ConfigureWebHostBuilder(IWebHostBuilder builder)
{
    builder.ConfigureAppWebHost(args);
    builder.ConfigureAppConfiguration(
        (context, configuration) =>
        {
            var section = context.Configuration.GetSection("kvSetting");
            var keyVaultUri = section.GetValue<string>("SecretUri");
            var clientId = section.GetValue<string>("ClientId");
            var clientSecret = section.GetValue<string>("ClientSecret");
            var tenantId = section.GetValue<string>("TenantId");

            if (
                string.IsNullOrWhiteSpace(keyVaultUri)
                || string.IsNullOrWhiteSpace(clientId)
                || string.IsNullOrWhiteSpace(clientSecret)
                || string.IsNullOrWhiteSpace(tenantId)
            )
                return;

            configuration.AddAzureKeyVault(
                new Uri(keyVaultUri),
                new ClientSecretCredential(tenantId, clientId, clientSecret)
            );
        }
    );
}