본문으로 건너뛰기
cccskills
무료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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

연동 도구Azure
설치 방법 보기

포함된 파일(2)

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

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

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

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

navikt/melosys-api22026년 10월 21일 업데이트

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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

navikt/melosys-api22026년 10월 21일 업데이트

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".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

navikt/melosys-api22026년 10월 21일 업데이트

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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

navikt/melosys-api22026년 10월 21일 업데이트

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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

navikt/melosys-api22026년 10월 21일 업데이트

brev

무료

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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

navikt/melosys-api22026년 10월 21일 업데이트

navikt의 스킬 모두 보기

이 스킬의 문제 신고