You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Som upstream Test-IDP for #1409 skal vi gjenbruke det eksisterende mock-prosjektet IdProvider ("MockPorten") (TheTechArch/IdProvider, gren master). En gjennomgang viser at den i dag er en mock som utsteder et gyldig token for en hvilken som helstpid uten autentisering. Stateless token-kjerne og Key Vault-/JWKS-infrastruktur er gjenbrukbar; hele autentiserings- og sikkerhetslaget mangler.
Denne issuen sporer herdingen av IdProvider slik at den oppfyller sikkerhetskravene i #1409. Den lastbærende invarianten (kun syntetisk Tenor-pid autentiseres, fail-closed) håndheves uansett også i altinn-authentication via RequireSyntheticPid (se #1409) — IdP-sjekken er forsvar i dybden.
Kodepekere under refererer TheTechArch/IdProvider på commit c848fbd.
Mål / akseptansekriterier
AK1: Ingen token utstedes uten korrekt delt tilgangspassord (ett secret som gir rett til å bruke Test-IDP — ingen brukernavn/per-bruker-passord, ingen Bridge siuser)
AK2: Delt passord verifiseres med konstant-tid-sammenligning; pid mottas kun via POST-body (aldri query/redirect/URL)
AK3: Kun velformet syntetisk Tenor-fnr (måned ∈ 81–92, gyldig mod11) slipper gjennom — fail-closed; alt annet access_denied
AK4: Test-IDP kan kun nås når klient er allowlistet og kall kom via PAR ogacr=urn:altinn:acr:test-idpogscope=altinn:testauthogprompt=login
AK5: PKCE (S256) håndheves; private_key_jwt valideres på /token; autorisasjonskode er engangsbruk
AK6: Korrekt OIDC-discovery (issuer/endepunkter/JWKS) slik at altinn-authentication kan validere tokens
AK7: Feature flag som slår hele Test-IDP av umiddelbart; metrikker/strukturert PII-fri logging/alarmer på plass
AK8: Et ordinært fnr kan aldri ende opp i et utstedt token (verifisert med test)
Gap-analyse og oppgaver
Alvorsgrad: 🔴 Kritisk · 🟠 Høy · 🟡 Medium · ⚪ Lav
1. Autentisering (delt tilgangspassord — ikke per-bruker)
Modell: ett delt tilgangspassord gir rett til å bruke Test-IDP. Identiteten er en inn-parameter — oppgi gyldig Tenor-fnr. Ingen brukernavn, ingen per-bruker-passord, ingen Bridge siuser. Sprengvidde er begrenset av Tenor-gaten (kun syntetiske identiteter) + kjedet opt-in (allowlistet private_key_jwt-klient via PAR). Se #1409.
### Autentisering
- [x] 🔴 Fjern `?pid=`-snarveien som utsteder kode uten interaksjon (AuthorizeController GET) — pid→token-orakel *(gjort, fase 1)*
- [ ] 🔴 Innfør delt-passord-validering: hent secret fra Key Vault; **konstant-tid-sammenligning**; aldri logg/ekko passordet
- [ ] 🔴 `pid` mottas kun via POST-body (aldri query/redirect/URL); fail-closed Tenor-sjekk før kode utstedes *(Tenor-gate gjort i fase 1; POST-only gjenstår)*
- [ ] 🟠 Rate-limit + lockout på delt-passord-sjekken (ASP.NET rate limiting; eneste brute-force-mål siden ett delt secret)
- [ ] 🟠 Per-miljø secret; harness henter fra CI-secret-store, helst OIDC workload-identity-federasjon (ingen langlivet secret lagret)
### Tenor-gate
- [x] 🔴 Implementer `IsSyntheticTenorPid` (11 siffer, måned ∈ 81–92, normaliser D-nummer dag−40, mod11) og avvis ikke-syntetisk med `access_denied` FØR kode utstedes *(gjort, fase 1 — `NorwegianIdentityNumber` + 15 enhetstester)*
- [ ] 🟠 Bekreft at `altinn-authentication` har tilsvarende `RequireSyntheticPid` (#1409) — IdP-sjekken er defence-in-depth, ikke eneste kontroll
3. Eksplisitt opt-in (kjedet routing)
### Opt-in
- [ ] 🟠 Klient-allowlist på `client_id` (ellers `unauthorized_client`)
- [ ] 🟠 Innfør `POST /par` (stateless: signert+kryptert `request_uri`-JWT); `/authorize` må kreve `request_uri` og avvise rå parametre
- [ ] 🟠 Krev `acr` inneholder `urn:altinn:acr:test-idp` (i dag bare ekko til token)
- [ ] 🟠 Krev `scope` inneholder `altinn:testauth`
- [ ] 🟡 Håndhev `prompt=login`
4. PKCE og klientautentisering på /token
### PKCE / client auth
- [ ] 🟠 Bind `code_challenge` inn i kode-JWT; verifiser `S256(code_verifier)==code_challenge` på `/token` (i dag ignoreres `code_verifier` helt), ellers `invalid_grant`
- [ ] 🟠 Valider `private_key_jwt` (iss/sub/aud/exp/jti + signatur mot Altinns registrerte JWKS)
- [ ] 🟠 Engangsbruk av autorisasjonskode (efemert konsumert-`jti`-sett; in-memory ved én instans, distribuert kun ved flere replicas)
5. Token-semantikk og output
### Token
- [ ] 🟡 Skill id_token og access_token (i dag returneres identisk token for begge; `refresh_token` er hardkodet "ADFSFDSFSDFDSFDSF")
- [ ] 🟡 Sett `amr=["pwd"]` (i dag hardkodet `["bankid"]`)
- [ ] 🟡 `acr=urn:altinn:acr:test-idp`; ingen `test=true`-claim (syntetisk fnr er markøren)
- [ ] 🟡 Bind og ekko `nonce` korrekt
6. Discovery / JWKS-korrekthet (OIDC-interop)
### Discovery
- [ ] 🟠 Én kanonisk `issuer` som matcher discovery `Issuer` (i dag avviker `IssCode`/`IssToken` fra discovery-issuer → Altinn token-validering feiler)
- [ ] 🟡 `AuthorizationEndpoint`/`TokenEndpoint` peker på faktiske ruter (`/Authorize`, `/token`), ikke base-URL
- [ ] 🟡 Legg til `pushed_authorization_request_endpoint`, `code_challenge_methods_supported=["S256"]`, `response_types_supported=["code"]` (i dag `["token"]`)
- [ ] 🟡 Fiks JWKS-path casing-mismatch (annonsert `/api/v1/OpenId/...` vs rute `/api/v1/openid/...`)
7. Observability og konfig
### Ops
- [x] 🟠 Feature flag (`TestIdpEnabled`, default av) som kortslutter alle endepunkter når av *(gjort, fase 1)*
- [ ] 🟠 Metrikker (authorize-forsøk, denied-non-synthetic, shared-password-failures) + strukturert logging UTEN `pid`/passord + alarmer
- [ ] 🟠 Konfigseksjon for allowlist/PAR/acr/scope + delt-passord-secret i Key Vault
- [ ] 🟠 Flytt hardkodet App Insights connection string ut av `appsettings.json` og rotér lekket ingestion-nøkkel
8. Øvrige defekter / opprydning
### Cleanup
- [ ] ⚪ Fiks `Response_mode = acr_values` copy-paste-bug i AuthorizeController
- [ ] 🟡 Refaktorer `IToken`-laget (auth-beslutning ligger i `GetAuthorizationCode`) — splitt i auth/validerings-tjeneste
- [ ] ⚪ Fjern ADAL/`Microsoft.Azure.KeyVault` (deprecated) — behold kun `Azure.Security.KeyVault`
- [ ] ⚪ Erstatt `Views/Authorize/Index.cshtml` (eksponerer alle OIDC-parametre som redigerbare felt) med kun `{ delt_passord, tenor_fnr }`
Skal nedstrøms acr være urn:altinn:acr:test-idp eller speile et ID-porten-nivå? (AuthenticationHelper.GetAuthenticationLevelForIdPorten i altinn-authentication må akseptere verdien)
Én IdP-instans (in-memory engangskode ok) eller HA-replicas (trenger distribuert dedupe)?
Trusselmodellering
### Trusselmodellering
- [ ] Åpner denne endringen for mulige nye trusler eller misbruk? (Test-IDP i prod — vurder pid-orakel, replay, kompromittert IdP som hevder reelt fnr)
Bakgrunn
Som upstream Test-IDP for #1409 skal vi gjenbruke det eksisterende mock-prosjektet
IdProvider("MockPorten") (TheTechArch/IdProvider, grenmaster). En gjennomgang viser at den i dag er en mock som utsteder et gyldig token for en hvilken som helstpiduten autentisering. Stateless token-kjerne og Key Vault-/JWKS-infrastruktur er gjenbrukbar; hele autentiserings- og sikkerhetslaget mangler.Denne issuen sporer herdingen av
IdProviderslik at den oppfyller sikkerhetskravene i #1409. Den lastbærende invarianten (kun syntetisk Tenor-pidautentiseres, fail-closed) håndheves uansett også ialtinn-authenticationviaRequireSyntheticPid(se #1409) — IdP-sjekken er forsvar i dybden.Mål / akseptansekriterier
siuser)pidmottas kun via POST-body (aldri query/redirect/URL)access_deniedacr=urn:altinn:acr:test-idpogscope=altinn:testauthogprompt=loginprivate_key_jwtvalideres på/token; autorisasjonskode er engangsbrukaltinn-authenticationkan validere tokensGap-analyse og oppgaver
Alvorsgrad: 🔴 Kritisk · 🟠 Høy · 🟡 Medium · ⚪ Lav
1. Autentisering (delt tilgangspassord — ikke per-bruker)
Modell: ett delt tilgangspassord gir rett til å bruke Test-IDP. Identiteten er en inn-parameter — oppgi gyldig Tenor-fnr. Ingen brukernavn, ingen per-bruker-passord, ingen Bridge
siuser. Sprengvidde er begrenset av Tenor-gaten (kun syntetiske identiteter) + kjedet opt-in (allowlistetprivate_key_jwt-klient via PAR). Se #1409.2. Testbruker-identifikasjon (Tenor) — lastbærende invariant
3. Eksplisitt opt-in (kjedet routing)
4. PKCE og klientautentisering på /token
5. Token-semantikk og output
6. Discovery / JWKS-korrekthet (OIDC-interop)
7. Observability og konfig
8. Øvrige defekter / opprydning
Beholdes (allerede tilstrekkelig)
JwtSigningCertificateProvider: Key Vault, versjonerte sertifikater, rollover, cachet, trådsikkernet9.0+AltinnHost/ServiceDefaultsAnbefalt rekkefølge
?pid=(1), Tenor fail-closed gate (2), feature flag default av (7) — ✅ gjort (fase 1)Åpne spørsmål (blokkerer design)
Er syntetiske Tenor-personer tilgjengelige via BridgeBortfalt — delt-passord-modell uten Bridge/per-bruker-kredential (besluttet; se Implementer Test-ID-provider (upstream) for automatiserte testkjøringer #1409)siuser?acrværeurn:altinn:acr:test-idpeller speile et ID-porten-nivå? (AuthenticationHelper.GetAuthenticationLevelForIdPorteni altinn-authentication må akseptere verdien)Trusselmodellering
Relatert: #1409