本文へ移動
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 / 1000 文字

このフォームは 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 のスキルをすべて見る

このスキルの問題を報告する