Altinn / Altinn/altinn-authentication

Systembruker for egenutviklet system

Open
#549 2 comments 0 reactions 0 assignees View on GitHub
Epic Etter19JuniRelease status/draft
Dominant language
C#
Stars
8
Forks
5
Avg merge
2d 21h
Merged PRs (30d)
21

Description

### Description

Formålet med denne epicen er å muliggjøre bruk av systembruker for **egenutviklede systemer** – integrasjoner en organisasjon utvikler for eget bruk og som ikke skal tilbys/vises til andre i systemregisteret.

I dag må man registrere et system i systemregisteret og manuelt knytte Maskinporten-klienten til dette systemet for å kunne ta i bruk en systembruker, også når systemet kun er til eget bruk. Det denne issuen skal utforske er **hvordan man kan knytte en Maskinporten-klient direkte til en systembruker**, slik at man slipper omveien om systemregisteret.

---

### Bakgrunn – hvorfor kreves et registrert system i dag?

Koblingen Maskinporten-klient → system → systembruker er i dag hardkodet gjennom systemregisteret:

- **Systembruker opprettes alltid mot et registrert system.** `SystemId` er påkrevd (`[Required]`) i `CreateRequestSystemUser`, og systemet må eksistere i systemregisteret og eies av vendor som oppretter forespørselen.
([`CreateRequestSystemUser.cs`](https://github.com/Altinn/altinn-authentication/blob/main/src/Core/Models/SystemUsers/CreateRequestSystemUser.cs#L27-L33))
- **Databasen håndhever dette** med en foreign key fra `system_user_profile.system_internal_id` til `system_register`.
- **Maskinporten-klienten (`client_id`) knyttes til systemet, ikke direkte til systembrukeren.** Ved innkommende token slås `client_id` opp mot `system_register.client_id`-arrayet (`@client_id = ANY (sr.client_id)`) via join til `system_user_profile`. Uten et registrert system med riktig `client_id` finnes det ingen systembruker å løse opp ved token exchange.
([`SystemUserRepository.cs`](https://github.com/Altinn/altinn-authentication/blob/main/src/Persistance/RepositoryImplementations/SystemUserRepository.cs#L351-L359))
- **`client_id` er globalt unik på tvers av systemer** – samme klient kan ikke ligge på to aktive systemer (`SystemRegister_ClientID_Exists`).
([`SystemRegisterController.cs`](https://github.com/Altinn/altinn-authentication/blob/main/src/Authentication/Controllers/SystemRegisterController.cs#L549-L565))

Det finnes et `IsVisible`-flagg på registrert system som skjuler systemet fra katalogen/brukergrensesnittet, men systemet må fortsatt registreres fullt ut. Det finnes **ingen egen «egenutviklet»-konsept** i koden i dag – det nærmeste er å registrere et skjult system (`isVisible=false`).

> Svar til @arneasv sitt spørsmål: Egenutviklede systemer «støttes» i dag kun i den forstand at man kan registrere et skjult system (`isVisible=false`) og opprette systembruker mot det. Man slipper altså ikke kravet om å registrere et system i systemregisteret og manuelt knytte Maskinporten-klienten til det. Det er nettopp denne friksjonen denne epicen skal fjerne.

---

### Hva skal utforskes

Hvordan kan en organisasjon knytte sin egen Maskinporten-klient direkte til en systembruker, uten å måtte registrere et (skjult) system i systemregisteret?

Mulige retninger å utrede:

1. **Opprett Maskinporten-klient direkte fra systembruker-grensesnittet** – la organisasjonen opprette/registrere en Maskinporten-klient som del av systembruker-flyten, slik at koblingen klient → systembruker skjer automatisk.
2. **List ut eksisterende Maskinporten-klienter** som organisasjonen eier og kan knytte til systembrukeren, og la bruker velge blant disse.

---

### Momenter som må avklares

- **Datamodell:** Kan `client_id` knyttes direkte til `system_user_profile`, eller trengs fortsatt et (auto-opprettet/implisitt) system bak? Konsekvens for FK og for oppslag ved token exchange.
- **Token exchange / oppslag:** Hvordan resolve systembruker fra `client_id` uten dagens `system_register`-join?
- **Unikhet:** `client_id` er i dag globalt unik per system. Hvordan håndteres unikhet når klienten knyttes direkte til en bruker?
- **Rettigheter / access packages:** I dag begrenses/arves systembrukerens rettigheter av det registrerte systemet. Hvordan defineres rettighetsomfang for en systembruker uten et bakenforliggende registrert system?
- **Maskinporten-integrasjon:** Behov for integrasjon mot Maskinporten/Samarbeidsportalen for å opprette og/eller liste klienter en organisasjon eier.
- **Tilgangsstyring:** Hvem kan opprette/knytte klienter (autorisasjon, scope, hvem eier klienten)?

---

### Observasjon: forenklet oppslag for egenutviklet system (provider == owner)

Ved token exchange resolves systembrukeren av det Maskinporten kommer med: `clientId` + `systemProviderOrgNo` (orgnr som eier klienten) + `systemUserOwnerOrgNo` (orgnr på eier/reportee av systembrukeren), evt. `externalRef` (defaulter til eier-orgnr).
([`SystemUserController.CheckIfPartyHasIntegration`](https://github.com/Altinn/altinn-authentication/blob/main/src/Authentication/Controllers/SystemUserController.cs#L150-L168))

For et **egenutviklet system** eier organisasjonen sin egen Maskinporten-klient **og** er reportee. Da blir `systemProviderOrgNo == systemUserOwnerOrgNo == externalRef` (alle = egen org). Leverandør/eier-skillet er altså degenerert i dette tilfellet.

**Konsekvens for design:** For egenutviklet-tilfellet trengs egentlig ikke vendor-/systemregister-indireksjonen for å identifisere brukeren – `client_id` + ett orgnr er nok til å slå opp «denne organisasjonens egen systembruker for denne klienten». Slik koden er i dag kreves systemet likevel: oppslaget joiner mot `system_register` og krever `client_id = ANY (sr.client_id)` **og** at `systemvendor_orgnumber` matcher ([`SystemUserRepository.cs`](https://github.com/Altinn/altinn-authentication/blob/main/src/Persistance/RepositoryImplementations/SystemUserRepository.cs#L351-L359)). Et mulig forenklet oppslag for direkte klient→systembruker: `(client_id + orgno)` uten `systemvendor_orgnumber`/system-join.

---

### Integrasjon mot Maskinporten – opprette eller liste klienter?

**Dagens tilstand:** Det finnes **ingen** integrasjon mot Maskinporten sitt administrasjons-API. `client_id` limes i praksis inn manuelt når et system registreres, lagres i `maskinporten_client`-tabellen, og valideres kun for lokal unikhet (`SystemRegister_ClientID_Exists`) – **ikke** for at organisasjonen faktisk eier klienten i Maskinporten. `GetMaskinportenClients` leser bare egen database, ikke Maskinporten.
([`SystemRegisterService.GetMaskinportenClients`](https://github.com/Altinn/altinn-authentication/blob/main/src/Authentication/Services/SystemRegisterService.cs#L129-L131) → lokal DB-spørring i [`SystemRegisterRepository`](https://github.com/Altinn/altinn-authentication/blob/main/src/Persistance/RepositoryImplementations/SystemRegisterRepository.cs#L644))

Dette betyr at man i dag reelt sett kan «poste en GUID kopiert fra Samarbeidsportalen» uten eierskapskontroll. Det bør ikke videreføres inn i en direkte klient→systembruker-kobling.

**Designvalg som må tas – opprette vs. liste:**

1. **Liste ut eksisterende Maskinporten-klienter** som organisasjonen eier, og la bruker velge blant disse.
- Krever integrasjon som kan lese organisasjonens klienter fra Maskinporten.
- Gir eierskapsverifisering «gratis» (man kan bare velge egne klienter), og løser «post en tilfeldig GUID»-svakheten.

2. **Opprette ny Maskinporten-klient direkte fra Altinn-grensesnittet.**
- Krever skrive-integrasjon mot Maskinporten sitt administrasjons-API.
- Da må vi ta stilling til **hvordan scopes legges på klienten.** Dette hører mest naturlig hjemme i Samarbeidsportalen. Alternativ: tilby en **direkte lenke** til klient-/scope-administrasjon i Samarbeidsportalen, i stedet for å reimplementere scope-styring i Altinn.

**Forutsetninger / antakelser (må verifiseres):**

- **Eierskapsverifisering:** Uansett alternativ må det bekreftes at klienten tilhører organisasjonen (ikke bare en innlimt GUID).
- **Maskinporten-avtale:** Å opprette/administrere klienter fra Altinn forutsetter at organisasjonen har inngått avtale med Maskinporten.
- **Autorisasjon:** Hvem i organisasjonen kan opprette/knytte klienter (rolle/tilgang), og hvilke scopes/tilganger kreves mot Maskinporten-API-et.
- **Ansvarsdeling:** Avklare grensesnittet Altinn ↔ Samarbeidsportalen (hva eies hvor: klientopprettelse, nøkler/hemmeligheter, scope-tildeling).

---

### In scope

- Utrede og beskrive løsningsalternativer for å knytte Maskinporten-klient direkte til en systembruker.
- Avklare konsekvenser for datamodell og for oppslag ved token exchange.
- Ta stilling til Maskinporten-integrasjon: liste ut eksisterende klienter vs. opprette nye fra Altinn, inkl. eierskapsverifisering og håndtering av scopes/avtale.

### Out of scope

- _(fylles ut)_

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reading CreateRequestSystemUser.cs, SystemUserRepository.cs, SystemUserController.cs, SystemRegisterController.cs, and the SystemRegisterService/SystemRegisterRepository client lookup. Compare the current system-register join, foreign-key model, token-exchange lookup, ownership checks, and Maskinporten integration assumptions. Done means documenting the viable direct-client designs and resolving the listed data-model, authorization, uniqueness, and integration decisions.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
authentication, authorization, backend-api-design, databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.