跳到正文
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(原文)

安装前可以查看交给 AI 代理的指令内容。

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 的全部技能

报告此技能的问题