Skip to content
cccskills
FreePublished on GitHub

security

Expert knowledge of authentication and authorization patterns in melosys-api. Use when: (1) Understanding Azure AD/OIDC authentication, (2) Debugging Tilgangsmaskinen access control, (3) Understanding SubjectHandler and user context, (4) Configuring OAuth2 clients for service-to-service calls, (5) Understanding audit logging patterns.

The English summary is being prepared. Showing the original description.

Works withAzure
See how to install

Files included (2)

  • SKILL.md9.1 KB
  • references/debugging.md4.4 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Security Skill

Expert knowledge of authentication and authorization in melosys-api.

Quick Reference

Authentication Methods

MethodPurposeUsage
Azure AD OIDCUser authenticationFrontend users (saksbehandler)
OAuth2 Client CredentialsService-to-serviceInternal NAV services
JWT BearerOn-behalf-ofUser context propagation
mock-oauth2-serverLocal developmentPorts 8082, 8086

Key Components

ComponentLocationPurpose
SubjectHandlersikkerhet/Get current user context
TilgangsmaskinenServiceservice/.../tilgangsmaskinen/Access control to person data
AuditLoggersikkerhet/.../logging/CEF audit logging
OAuth2 Configapplication.ymlOAuth2 client config

SubjectHandler

Access current user context from anywhere in the application.

// Get current user
val userId = SubjectHandler.getSaksbehandlerIdent()
val userName = SubjectHandler.getInstance().getUserName()
val groups = SubjectHandler.getInstance().getGroups()

// Get user or system user fallback
val userOrSystem = SubjectHandler.getUserIDOrSystemUser()

// Get OIDC token for propagation
val token = SubjectHandler.getInstance().getOidcTokenString()

System User

SubjectHandler is a Java class; SYSTEMBRUKER is a public static field (not a Kotlin companion object).

// SubjectHandler.java
public static String SYSTEMBRUKER = "srvmelosys";

Tilgangsmaskinen (Access Control)

Replaces legacy ABAC system for access control to person data.

@Service
class TilgangsmaskinenService(
    private val tilgangsmaskinenClient: TilgangsmaskinenClient,
    private val persondataService: PersondataService
) {
    @Cacheable(value = ["tilgangsmaskinen"], key = "#fnr + '_' + T(no.nav.melosys.sikkerhet.context.SubjectHandler).getInstance().getUserID()")
    fun sjekkTilgangTilFnr(fnr: String): Boolean {
        return tilgangsmaskinenClient.sjekkTilgang(fnr, RegelType.KOMPLETT_REGELTYPE)
    }

    @Cacheable(value = ["tilgangsmaskinen"], key = "#aktørId + '_' + T(no.nav.melosys.sikkerhet.context.SubjectHandler).getInstance().getUserID()")
    fun sjekkTilgangTilAktørId(aktørId: String): Boolean {
        val fnr = hentFnrFraPdl(aktørId)
        return tilgangsmaskinenClient.sjekkTilgang(fnr, RegelType.KOMPLETT_REGELTYPE)
    }
}

Usage in Services

Inject the Aksesskontroll interface (implemented by TilgangsmaskinenAksesskontroll). Its methods include auditAutoriser(behandlingID, kontekst), auditAutoriserSkriv(behandlingID, kontekst), auditAutoriserAktørID(aktørID, kontekst) and autoriserSakstilgang(saksnummer).

@Service
class MyService(
    private val aksesskontroll: Aksesskontroll
) {
    fun doSomething(behandlingID: Long) {
        aksesskontroll.auditAutoriser(behandlingID, "MyService.doSomething")
        // Throws SikkerhetsbegrensningException if access denied
    }
}

OAuth2 Client Configuration

Client Types

Grant TypeUse Case
client_credentialsService-to-service (no user context)
urn:ietf:params:oauth:grant-type:jwt-bearerOn-behalf-of (with user context)

Configuration Structure

no.nav.security.jwt:
  client:
    registration:
      pdl:  # Client name
        authentication:
          client-auth-method: client_secret_basic
          client-id: ${AZURE_APP_CLIENT_ID}
          client-secret: ${AZURE_APP_CLIENT_SECRET}
        grant-type: urn:ietf:params:oauth:grant-type:jwt-bearer
        scope: api://${NAIS_CLUSTER_NAME}.pdl.pdl-api/.default
        token-endpoint-url: ${AZURE_OPENID_CONFIG_TOKEN_ENDPOINT}

Registered Clients

The authoritative list lives in the registration: block of app/src/main/resources/application.yml (it drifts as integrations are added). As of this writing:

ClientGrant TypeTarget
aaregjwt-bearerAareg (arbeidsforhold)
faktureringskomponentenjwt-bearerBilling
felleskodeverkjwt-bearerFelles kodeverk
graphclient_credentialsMicrosoft Graph
inntektclient_credentialsInntektskomponenten
medljwt-bearerMEDL
melosys-eessijwt-bearerEESSI
oppgavejwt-bearerOppgave
pdljwt-bearerPDL
safjwt-bearerSAF
sokos-utbetaldatajwt-bearerUtbetalingsdata
tilgangsmaskinenjwt-bearerTilgangsmaskinen
melosys-soknad-mottakjwt-bearerSøknad mottak
melosys-skjemajwt-bearerSkjema API
dokarkivjwt-bearerJoark
dokdistfordelingjwt-bearerDocument distribution

Audit Logging

CEF (Common Event Format) logging for security events.

@Component
class AuditLogger {
    fun log(auditEvent: AuditEvent) {
        audit.info { createCommonEventFormatString(auditEvent) }
    }
}

data class AuditEvent(
    val type: AuditEventType,
    val sourceUserId: String,
    val destinationUserId: String,
    val message: String? = null,
    val sourceProcessName: String? = null
)

enum class AuditEventType {
    READ, UPDATE
}

Log Format

CEF:0|melosys|Auditlog|1.0|audit:read|Medlemskap og lovvalg|INFO|
suid=Z123456 duid=12345678901 end=1703318400000 requestMethod=GET
request=/api/fagsak/123 sproc=FagsakController msg=Hentet fagsak

Token Validation

NAIS Configuration

no.nav.security.jwt:
  issuer:
    aad:
      accepted-audience: ${AZURE_APP_CLIENT_ID}
      discoveryurl: ${AZURE_APP_WELL_KNOWN_URL}

Token Claims

ClaimDescription
NAVidentSaksbehandler ID (e.g., Z123456)
nameUser's full name
groupsAD group memberships
audAudience (client ID)

Local Development

mock-oauth2-server

Ports:

  • 8082: Main OAuth server
  • 8086: Alternative port

Configuration

# application-local-mock.yml
AZURE_APP_CLIENT_ID: '"lol"'
AZURE_APP_CLIENT_SECRET: '"lol"'
AZURE_OPENID_CONFIG_TOKEN_ENDPOINT: http://host.docker.internal:8082/isso/token

Test Token

@EnableMockOAuth2Server
class MyIT {
    @Autowired
    private lateinit var mockOAuth2Server: MockOAuth2Server

    val token = mockOAuth2Server.issueToken(
        issuerId = "aad",
        subject = "Z123456",
        claims = mapOf("NAVident" to "Z123456")
    ).serialize()
}

Admin Endpoints Security

Admin endpoints under /admin/** are @Protected (token-support) controllers, additionally gated by AdminTilgangInterceptor (frontend-api/.../tjenester/gui/config/AdminTilgangInterceptor.kt). There is no shared admin API key anymore (MELOSYS-8271); the X-MELOSYS-ADMIN-APIKEY header is ignored.

Access rules

  • No valid aad token: the interceptor lets the request through and @Protected returns 401.
  • The token's azp must be one of Melosys-admin.console-klient-id (melosys-console's client ID). Otherwise 403. In nais the value comes from MELOSYS_CONSOLE_CLIENT_ID (nais/vars-*.json).
  • User calls (OBO) also require the ops group Melosys-admin.driftsgruppe in the groups claim. Otherwise 403.
  • Machine calls (idtyp = app) from melosys-console may call all admin endpoints.

RestControllerInterceptor marks requests under /admin/ as admin requests, so downstream calls use the system token (ThreadLocalAccessInfo.shouldUseSystemToken()).

/api/admin/** endpoints in no.nav.melosys.tjenester.gui (e.g. TekstblokkAdminController) are not covered by the interceptor; they only have @Protected.

In local-mock the client IDs are the azp values of the local mock tokens (melosys-api for melosys-console, melosys-localhost for the e2e token).

Error Handling

SikkerhetsbegrensningException

Thrown when access is denied (in TilgangsmaskinenAksesskontroll, package no.nav.melosys.exception):

throw SikkerhetsbegrensningException("Tilgangsmaskinen: Brukeren har ikke tilgang til ressurs")

TilgangsmaskinenException

Thrown on technical errors:

throw TilgangsmaskinenException("Feil ved tilgangssjekk", cause)

Caching

Access control results are cached:

@Cacheable(
    value = ["tilgangsmaskinen"],
    key = "#fnr + '_' + T(no.nav.melosys.sikkerhet.context.SubjectHandler).getInstance().getUserID()"
)
fun sjekkTilgangTilFnr(fnr: String): Boolean

Cache key includes both the person ID and the user ID to ensure user-specific results.

References

  • references/debugging.md — step-by-step debugging for token validation, access-denied, OAuth2 client, and mock-OAuth issues.

Related Skills

  • person: PDL integration uses OAuth2
  • journalforing: SAF/Joark integration
  • oppgave: Oppgave API authentication
  • eessi-eux: EESSI/EUX authentication

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Expert knowledge of Altinn A1 application processing for posted workers in melosys-api. Use when: (1) Understanding Altinn søknad/skjema processing, (2) Debugging MedlemskapArbeidEOS form mapping, (3) Understanding SoeknadMapper transformations, (4) Investigating posted worker application issues, (5) Understanding the MOTTAK_SOKNAD_ALTINN saga flow.

The English summary is being prepared. Showing the original description.

navikt/melosys-api2Updated Oct 21, 2026

Expert knowledge of Employer/Employment integration (EREG/AAREG) in melosys-api. Use when: (1) Working with organization data from EREG (Enhetsregisteret), (2) Working with employment data from AAREG (Arbeidsforhold), (3) Understanding employer/organization lookup, (4) Debugging employer or employment issues, (5) Understanding the mapping between register data and domain models. Triggers: orgnummer, arbeidsforhold, EREG, AAREG, Enhetsregisteret, registeropplysninger, ansettelsesperiode, saksopplysning.

The English summary is being prepared. Showing the original description.

navikt/melosys-api2Updated Oct 21, 2026

Modular monolith architecture overview for melosys-api. Use when needing to understand module structure, dependencies between modules, where to place new code, or when changes in one module might affect others. Triggers: "architecture", "module dependencies", "where should I put", "which modules", "dependency graph".

The English summary is being prepared. Showing the original description.

navikt/melosys-api2Updated Oct 21, 2026

Expert knowledge of Behandling (case treatment) domain in melosys-api. Use when: (1) Understanding the behandling lifecycle and status transitions, (2) Debugging issues with behandling creation, status changes, or closure, (3) Understanding relationships between Fagsak, Behandling, and Behandlingsresultat, (4) Investigating why a behandling is stuck or has wrong status, (5) Understanding Behandlingstyper, Behandlingstema, Behandlingsstatus enums, (6) Debugging journalføring or SED-triggered behandling creation, (7) Understanding behandling creation via saksflyt sagas.

The English summary is being prepared. Showing the original description.

navikt/melosys-api2Updated Oct 21, 2026

Expert knowledge of Behandlingsresultat (treatment result) domain in melosys-api. Use when: (1) Understanding result types and their meaning (FASTSATT_LOVVALGSLAND, MEDLEM_I_FOLKETRYGDEN, etc.), (2) Working with periods - Lovvalgsperiode, Medlemskapsperiode, Anmodningsperiode, Utpekingsperiode, (3) Debugging vedtak/decision metadata, criteria evaluation, or social insurance charges, (4) Understanding EU/EEA coordination logic and Article 16 exception handling, (5) Working with trygdeavgift (social insurance charge) calculations.

The English summary is being prepared. Showing the original description.

navikt/melosys-api2Updated Oct 21, 2026

brev

Free

Expert knowledge of Brev (letter generation) in melosys-api. Use when: (1) Producing letters and decision documents (vedtaksbrev), (2) Understanding Dokgen templates and mapping, (3) Configuring letter recipients and distribution, (4) Debugging letter generation issues, (5) Adding new letter types or templates.

The English summary is being prepared. Showing the original description.

navikt/melosys-api2Updated Oct 21, 2026

See all skills by navikt

Report a problem with this skill