Spring Boot service that persists Flyt user permissions, answers client authorization requests, and exposes internal APIs for managing user access. It maps configured SSO client IDs to source applications, synchronizes permissions to Kafka, and provisions new users from JWT claims when they first sign in.
- Internal OAuth2 APIs — web-resource-server profile locks down
/api/intern/authorizationendpoints and enforces admin roles for management actions. - Kafka request/reply — listens for
client-idauthorization requests and replies with source application mappings using the FINT Kafka request/reply utilities. - Permission sync — persists users in Postgres and emits
userpermissionentity events whenever users are created, updated, or bulk-synced. - Permission auditing — keeps an Envers history of
user_entityandsourceApplicationIdschanges in dedicated audit tables with actor metadata. - Role-gated onboarding — accepts users only when their token roles match a configured allow-list and auto-grants admins access to all source applications.
- Scheduled publishing — optional scheduler republishes all user permissions on a fixed delay to keep downstream caches in sync.
| Component | Responsibility |
|---|---|
ClientAuthorizationRequestConfiguration |
Provisions the Kafka request topic (authorization / client-id) and hosts the listener that responds to client ID lookups. |
ClientAuthorizationProducerRecordBuilder |
Resolves incoming client IDs to ClientAuthorization replies with the correct sourceApplicationId, or marks them unauthorized. |
AcosSourceApplication, DigisakSourceApplication, EgrunnervervSourceApplication, VigoSourceApplication, AltinnSourceApplication, HMSRegSourceApplication |
Bind SSO client IDs from properties and expose static source-application IDs used in authorization replies. |
UserService |
Core business logic for persisting users, mapping DTOs/entities, and emitting UserPermission Kafka events. |
UserRepository |
Spring Data JPA repository for UserEntity storage and lookups by objectIdentifier. |
UserPermissionEntityProducerService |
Produces last-value userpermission events to Kafka with a 4-day retention window. |
UserPublishingComponent |
Conditional scheduler that republishes all users at configured intervals. |
UserController |
Admin-only internal API for paginating users and bulk updating sourceApplicationIds. |
MeController |
Self-service internal API that provisions users from JWT claims, reports restricted-page access, and returns the current user. |
TokenParsingUtils / AccessControlProperties |
Parse JWT claims, check permitted app roles, and detect ROLE_ADMIN authority. |
Base path: /api/intern/authorization
| Method | Path | Description | Request body | Response |
|---|---|---|---|---|
GET |
/me |
Returns the current user; creates one from JWT claims when absent (admins are granted all source application IDs). | – | 200 OK with User JSON. |
GET |
/me/is-authorized |
Confirms the caller has a permitted role; provisions the user when missing. | – | 200 OK with a confirmation string. |
GET |
/me/restricted-page-authorization |
Indicates whether the caller can access the user-permission page (ROLE_ADMIN). |
– | 200 OK with RestrictedPageAuthorization. |
GET |
/users |
Admin-only paginated list of users (page, size, sort supported). |
– | 200 OK with a Page<User> or 403 when unauthorized. |
POST |
/users/actions/userPermissionBatchPut |
Admin-only bulk upsert of user permissions, then republishes all users. | JSON array of User objects (objectIdentifier, email, name, sourceApplicationIds). |
200 OK or 403 on insufficient role. |
Errors are surfaced as standard Spring MVC responses (403 Forbidden when the caller lacks admin authority).
- Request/reply consumer — provisions the
authorizationrequest topic (resourceauthorization, parameterclient-id) with 10-minute retention and responds withClientAuthorizationpayloads for known SSO client IDs. - Entity producer — publishes
userpermissionentity events (partition count: 1, last/null-value retention: 4 days) whenever users are saved or bulk-updated; replay is also triggered by the scheduled publisher. - Topic names are built with
orgId/domainContextprefixes fromnovari.kafka.topic.*and the FINT Kafka templating services.
UserPublishingComponent.publishUsers() Defaults: initial delay 1s, fixed delay 12h. Each run republishes all stored users as UserPermission events.
The application includes the shared Spring profiles flyt-kafka, flyt-logging, flyt-postgres, and flyt-web-resource-server.
Key properties:
| Property | Description |
|---|---|
fint.application-id |
Defaults to fint-flyt-authorization-service. |
novari.flyt.authorization.access-control.permitted-approles.* |
Map of allowed app roles (e.g., flyt-user, flyt-developer) to role URIs used when onboarding users. |
novari.flyt.authorization.access-control.enabled |
Enables the scheduled user-permission publisher. |
novari.flyt.authorization.access-control.sync-schedule.initial-delay-ms / fixed-delay-ms |
Interval settings for the publisher task. |
fint.flyt.<app>.sso.client-id |
Client IDs for Acos, Digisak, Egrunnerverv, Vigo, Altinn, and HMSReg; mapped to source application IDs 1–6. |
novari.kafka.topic.domain-context / novari.kafka.topic.org-id |
Prefixes for Kafka topics and ACLs. |
spring.datasource.* |
JDBC details for Postgres; Flyway migrations live under classpath:db/migration. |
spring.security.oauth2.resourceserver.jwt.issuer-uri |
OAuth issuer for protecting internal endpoints. |
novari.flyt.web-resource-server.security.api.internal.authorized-org-id-role-pairs-json |
Defines which org/role pairs may call internal APIs (injected by overlays). |
spring.kafka.consumer.group-id |
Defaults to the application ID. |
Secrets referenced by Kustomize overlays must provide database credentials, OAuth settings, Kafka access, and SSO client IDs. The service now binds only fint.flyt.<app>.sso.client-id from these secrets; client-secret values are not injected into the application environment.
Prerequisites:
- Java 25+
- Docker (for the bundled Postgres helper) and access to a Kafka broker
- Gradle (wrapper included)
Useful commands:
./start-postgres # launch Postgres on localhost:5435
SPRING_PROFILES_ACTIVE=local-staging ./gradlew bootRun # start with local defaults
./gradlew ktlintFormat build # format, compile, and run tests
./gradlew ktlintCheck # run ktlint only
./gradlew test # run unit tests onlyThe local-staging profile points to localhost:9092 for Kafka and configures database credentials/schema for local use. Override fint.flyt.<app>.sso.client-id and access-control properties as needed for experiments.
Kustomize layout:
kustomize/base/contains the sharedApplicationresource and OAuth/OnePassword references for each upstream SSO client.kustomize/overlays/<org>/<env>/applies namespace labels, Kafka org IDs, URL base paths, and authorized org/role pairs per organization and environment.
Templates are centralized in kustomize/templates/:
overlay.yaml.tpl—envsubsttemplate rendered for every overlay.
Regenerate overlays after changing the template or rendering logic:
./script/render-overlay.shThe script injects namespace-specific values (base paths, Kafka topics, authorized org-role pairs) and rewrites each kustomization.yaml in place.
- Uses the FINT OAuth2 web-resource-server setup for JWT validation (
spring.security.oauth2.resourceserver.jwt.issuer-uri). - Internal APIs are restricted to callers whose org/role pairs are configured; management endpoints additionally require
ROLE_ADMIN. - Client-authorization replies are limited to explicitly configured SSO client IDs per source application.
- Readiness and liveness:
/actuator/health. - Metrics:
/actuator/prometheus. flyt_authorization_source_application_availableexposes enabled source applications per org (tags:org_id,sourceapplication_id,source_application).flyt_authorization_source_application_infoexposes source-application metadata per org for label enrichment in Grafana (tags:org_id,sourceapplication_id,source_application).- Structured logging via the shared logging profile; Kafka request/reply and user-permission publishing emit detailed log messages for traceability.
- When adding a new source application, supply its
fint.flyt.<app>.sso.client-id, assign a uniqueSOURCE_APPLICATION_ID, and update the builder test. - If access-control role mappings change, adjust
novari.flyt.authorization.access-control.permitted-approlesand ensure admins still get fullsourceApplicationIdsinMeController. - Bulk updates trigger Kafka publishes; keep database schema and
UserPermissionconsumers aligned when altering user fields. - User-permission changes are now audited in
user_entity_aud,user_entity_source_application_ids_aud, andrevinfo; inspect those tables when validating access changes. - Update
script/render-overlay.shif additional organizations need custom role mappings or path prefixes.
- Create a topic branch for your change.
- Run
./gradlew test(and additional checks) before raising a PR. - If you modify Kustomize templates or overlay logic, rerun
./script/render-overlay.shand commit the generated manifests. - Add or adjust tests for any new behaviour or edge cases.
FINT Flyt Authorization Service is maintained by the FINT Flyt team. Reach out via the internal Slack channel or open an issue in this repository for questions or enhancements.