Sist endret: 30. jul. 2025

Integrasjon av Altinn-app med Maskinporten

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

Denne veiledningen viser hvordan du setter opp en Altinn-applikasjon til å bruke den innebygde Maskinporten-klienten (IMaskinportenClient) for å utføre autoriserte forespørsler på vegne av eieren av applikasjonen, i stedet for den aktive brukeren.

For å sette dette opp, må følgende gjøres:

  1. Sørg for at organisasjonen har tilgang til Azure Key Vault.
  2. Opprett en Maskinporten-integrasjon i selvbetjeningsportalen.
  3. Lagre autentiseringsnøkkelen for integrasjonen i Azure Key Vault.
  4. Sett opp applikasjonen til å bruke Maskinporten-klienten og hente hemmeligheter fra Azure Key Vault.

Tilgang til Azure Key Vault

Før du går videre med denne veiledningen, må du forsikre deg om at du har tilgang til Azure Key Vault for organisasjonen din. Dette sikrer at nøklene som opprettes senere i veiledningen kan lagres riktig som hemmeligheter i Azure.

Hvis tilgang mangler, se Tilgang til logger og hemmeligheter.

Maskinporten-integrasjon

I denne delen skal vi sette opp Maskinporten-klienten. En del av oppsettet inkluderer opprettelse av nøkler som senere skal lagres i Azure Key Vault. Hvis ulike personer i organisasjonen har tilgang til forskjellige ressurser som trengs i forbindelse med dette, anbefales det å samarbeide og utføre disse trinnene på samme maskin. På den måten unngår man å sende hemmeligheter mellom personer og maskiner.

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

Maskinporten-klienter opprettes i selvbetjeningsportalen:

  1. Start med å logge inn på kontoen din med valgt metode.
  2. Når du er logget inn på kontoen din, vises organisasjonen du representerer i toppmenyen til høyre.
    Organisasjonen du representerer vises i toppmenyen
    Organisasjonen du representerer vises i toppmenyen.
    Hvis du logget inn for å representere en syntetisk organisasjon, vil du også kunne endre den organisasjonen du representerer i nedtrekksmenyen på det elementet.
    Du kan endre syntetisk organisasjon i nedtrekksmenyen
    Du kan endre den syntetiske organisasjonen du representerer i nedtrekksmenyen.
  3. Velg Opprett klient-knappen for å begynne å opprette en ny klient for organisasjonen du representerer.
  4. Velg MaskinportenLegg til klient-siden.
  5. Legg til Maskinporten klient-siden fyll inn visningsnavn, beskrivelse og legg til dine nødvendige scopes (disse verdiene kan også endres senere). Klikk deretter Opprett-knappen.
    Siden for å legge til Maskinporten-klient
    Siden for å legge til Maskinporten-klient.
  6. Du har nå opprettet en Maskinporten-klient for din organisasjon. For å bruke denne klienten må du legge til minst én autentiseringsnøkkel. Klienten støtter JWK- og PEM-nøkler. Start med å enten finne en eksisterende nøkkel eller opprette en ny. Du kan bruke Altinn JWKS-verktøyet eller annen nøkkelgenerator du ønsker til dette formålet. Naviger deretter til nøkkelseksjonen på klientsiden din og velg Legg til.
    Velg nøkkelseksjonen på klientsiden din
    Nøkler kan legges til i nøkkelseksjonen.
    I feltet JWK eller PEM format lim inn din offentlige nøkkel og klikk Lagre. Nøkkelen er nå lagt til klienten. Lagre din private nøkkel fra din JWK eller PEM på et sikkert sted, da den brukes til å autorisere bruken av denne klienten. Hvis du bruker Azure Key Vault for å lagre dine private nøkler, må de være base64-kodet før opplasting.
    Lim inn din offentlige nøkkel her
    Den offentlige JWK- eller PEM-nøkkelen limes inn i dette feltet
  7. Hvis du ikke gjorde det i trinn 5, må du legge til ønskede scopes til klienten din før den kan brukes.
    Legge til scopes til klienten
    Fra Scopes-fanen på klientdefinisjonen din, klikk Legg til-knappen.
    Legge til scopes til klienter
    Scopes som er tilgjengelige for organisasjonen din vil vises i listen. Velg de nødvendige og klikk Send inn.

Konfigurasjon av Azure Key Vault

Når applikasjonen forberedes til å bruke hemmeligheter fra Azure Key Vault, må følgende trinn utføres:

  1. Legg til hemmelighetene som ble hentet under konfigurasjon 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 tilsvarer navnet på seksjonen i appsettings-filen i kodebasen til applikasjonen. F.eks. hvis din appsettings-seksjon for Maskinporten-integrasjonen ser slik ut:

    {
      "MaskinportenSettings": {
        "Authority": "https://test.maskinporten.no/",
        "ClientId": "",
        "JwkBase64": ""
      }
    }
    

    Skal hemmelighetene i Azure Key Vault ha navn som dette:

    MaskinportenSettings--Authority
    MaskinportenSettings--ClientId
    MaskinportenSettings--JwkBase64
    
  2. For at applikasjonen skal kunne lese hemmelighetene fra Azure Key Vault, må den konfigureres til å gjøre det. Se secrets-seksjonen for å oppnå dette.

  3. Legg til appsettings-eksempelet ovenfor i appsettings.{env}.json-filen.

Merk: Hemmelighetene leses av applikasjonen ved oppstart, så hvis du gjør endringer etter at applikasjonen er publisert, må du publisere applikasjonen på nytt for at de skal tre i kraft.

Applikasjonsoppsett

Applikasjonen inkluderer automatisk den innebygde IMaskinportenClient som kan brukes i tjenestene dine.

Konfigurasjonsstier

Klienten vil automatisk lete etter en Maskinporten-konfigurasjon på standardstien “MaskinportenSettings”. Hvis du ønsker å bruke en annen sti, kanskje fordi du administrerer flere apper og hver av dem trenger ulik autorisasjon, kan du konfigurere dette via ConfigureMaskinportenClient-metoden.

void RegisterCustomAppServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment env)
{
  // ...

  services.ConfigureMaskinportenClient(
      "YourCustomMaskinportenSettingsPath"
  );
}

Autorisering av Http-klienter

Typede og navngitte Http-klienter kan autoriseres med de tilgjengelige utvidelsesmetodene, som illustrert nedenfor.

void RegisterCustomAppServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment env)
{
  // ...

  // For external APIs that require raw Maskinporten tokens
  services.AddHttpClient<CustomClient1>().UseMaskinportenAuthorization("scope1", "scope2");
  services.AddHttpClient("named-client1").UseMaskinportenAuthorization("scope1", "scope2");

  // For Altinn APIs that require Altinn tokens (exchanges Maskinporten token)
  services.AddHttpClient<CustomClient2>().UseMaskinportenAltinnAuthorization("scope1", "scope2");
  services.AddHttpClient("named-client2").UseMaskinportenAltinnAuthorization("scope1", "scope2");
}

Manuell bruk

Hvis du trenger å hente et Maskinporten-token manuelt, kan du bruke IMaskinportenClient i tjenesten din og hente tokens med GetAccessToken- og GetAltinnExchangedToken-metodene.

public class Example(IMaskinportenClient maskinportenClient) : IProcessTaskEnd
{
  public async Task End(string taskId, Instance instance)
  {
    var maskinportenToken = await maskinportenClient.GetAccessToken(["scope1", "scope2"]);
    var altinnExchangedToken = await maskinportenClient.GetAltinnExchangedToken(["scope1", "scope2"]);

    // Do something with the tokens...
  }
}

Key Vault-konfigurasjon

Til slutt må vi legge til Azure Key Vault-konfigurasjonsleverandøren til vår host. Dette gjøres ved å legge til den markerte koden etter ConfigureWebHostBuilder-metoden.

//...

ConfigureWebHostBuilder(IWebHostBuilder builder);

// Add Azure KV provider for TT02 & Prod environments
if (!builder.Environment.IsDevelopment())
{
  builder.AddAzureKeyVaultAsConfigProvider();
}

Bakoverkompatibilitet

IMaskinportenTokenProvider

Visse eldre tjenester krever en implementering av IMaskinportenTokenProvider for å hente tokens. MaskinportenClient vil automatisk registrere denne tjenesten hvis den ikke allerede er registrert andre steder.

Altinn.ApiClients.Maskinporten

Hvis du trenger å støtte eksisterende bruk av den frittstående Maskinporten-klienten, mens du samtidig vil bruke den innebygde klienten for nye funksjoner, gir det vanligvis mening å utnytte én enkelt Azure Key Vault-konfigurasjon.

Eksempelet nedenfor illustrerer hvordan du kan omforme et Altinn.ApiClients.Maskinporten.Config.MaskinportenSettings-objekt til formatet som kreves av den innebygde klienten.

using Altinn.App.Core.Features.Maskinporten.Exceptions;
using LegacyMaskinportenSettings = Altinn.ApiClients.Maskinporten.Config.MaskinportenSettings;
// ...

void RegisterCustomAppServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment env)
{
  // ...

  var legacySettings =
    config.GetSection("Maskinporten-Config-Path").Get<LegacyMaskinportenSettings>()
    ?? throw new MaskinportenConfigurationException("Maskinporten settings not found in config.");

  services.ConfigureMaskinportenClient(options =>
  {
    options.ClientId = legacySettings.ClientId;
    options.JwkBase64 = legacySettings.EncodedJwk;
    options.Authority = legacySettings.Environment switch
    {
      "prod" => "https://maskinporten.no/",
      "test" => "https://test.maskinporten.no/",
      "dev" => "https://maskinporten.dev/",
      _ => throw new MaskinportenConfigurationException($"Unknown Maskinporten environment value {legacySettings.Environment}")
    };
  });
  
  // More information about the Maskinporten environment mapping:
  // https://github.com/Altinn/altinn-apiclient-maskinporten/blob/main/src/Altinn.ApiClients.Maskinporten/Services/MaskinportenService.cs#L343
}

Migreringsveier

I denne seksjonen finner du noen korte eksempler på hvordan du kan migrere din eksisterende konfigurasjon fra den frittstående Maskinporten-klienten til den innebygde.

Bruk av AddMaskinportenHttpClient

Følgende eksempel viser hvordan en EventSubscriptionClient tradisjonelt har blitt konfigurert, og hvordan du kan oppnå samme resultat ved å bruke den innebygde Maskinporten-klienten.

void RegisterCustomAppServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment env)
{
  // ...

  // Before: Altinn.ApiClients.Maskinporten client configuration
  services
    .AddMaskinportenHttpClient<SettingsJwkClientDefinition, EventsSubscriptionClient>(
      config.GetSection("Maskinporten-Config-Path"),
      clientDefinition =>
      {
        clientDefinition.ClientSettings.Scope = "altinn:serviceowner/instances.read";
        clientDefinition.ClientSettings.ExhangeToAltinnToken = true;
      }
    )
    .AddTypedClient<IEventsSubscription, EventsSubscriptionClient>();

  // After: Built-in client configuration
  services.ConfigureMaskinportenClient("Maskinporten-Config-Path");
  services
    .AddHttpClient<IEventsSubscription, EventsSubscriptionClient>()
    .UseMaskinportenAltinnAuthorization("altinn:serviceowner/instances.read");
}

Bruk av AddMaskinportenHttpMessageHandler

Følgende eksempel viser hvordan Altinn.ApiClients.Dan typisk har blitt konfigurert, og hvordan du kan oppnå samme resultat ved å bruke den innebygde Maskinporten-klienten.

void RegisterCustomAppServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment env)
{
  // ...

  // Before: Altinn.ApiClients.Maskinporten client configuration
  services.RegisterMaskinportenClientDefinition<SettingsJwkClientDefinition>(
    "client-name",
    config.GetSection("Maskinporten-Config-Path")
  );

  services
    .AddDanClient(config.GetSection("Dan-Config-Path"))
    .AddMaskinportenHttpMessageHandler<SettingsJwkClientDefinition>(
      "client-name",
      clientDefinition =>
      {
        clientDefinition.ClientSettings.Scope = "altinn:dataaltinnno";
      }
    );

  // After: Built-in client configuration
  services.ConfigureMaskinportenClient("Maskinporten-Config-Path");
  services
    .AddDanClient(config.GetSection("Dan-Config-Path"))
    .UseMaskinportenAuthorization("altinn:dataaltinnno");
}