
This page is for those who run a server built on the Spring Authentication Server. It describes what the server adds
to Spring Boot Actuator: an endpoint that shows
and updates the clients that the server knows, what the server adds to the info endpoint, its health indicators,
the state that the server keeps between restarts, and the audit events that tell when a client appears or
disappears.
Source links in this guide point to the main branch of the
spring-authentication-server repository.
The Actuator support is active when Spring Boot Actuator is on the classpath. The starters do not bring it, so add it to the application:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Without it the server works as before; only the endpoint, the info contributions and the health indicators are missing.
Which endpoints are exposed, on which port, and who may call them is decided by the deployment, as for any Actuator endpoint. See Endpoints in the Spring Boot documentation. For example:
management:
server:
port: 8444
endpoints:
web:
exposure:
include: health, info, clients, auditevents
endpoint:
health:
show-details: always
The examples on this page assume that the endpoints are found under /actuator.
Path: /actuator/clients
The clients endpoint shows the clients that the client registry holds, for both protocols,
and updates their data on request. The identity of a client is given as the query parameter id, since identities
are usually URLs.
| Operation | Description |
|---|---|
GET /actuator/clients |
Lists every client that the server holds now. |
GET /actuator/clients/saml?id=... |
Shows one SAML Service Provider. |
GET /actuator/clients/oidc?id=... |
Shows one OpenID Connect client. |
GET /actuator/clients/saml/metadata?id=... |
Gives the EntityDescriptor of a Service Provider as XML, exactly as held. |
GET /actuator/clients/oidc/metadata?id=... |
Gives the metadata of an OpenID Connect client as JSON, exactly as held, except that a client secret is left out. |
POST /actuator/clients/saml |
Updates the SAML metadata. No source is named; every metadata source that can be updated is downloaded or read again. |
POST /actuator/clients/oidc?id=... |
Drops an OpenID Federation client from the cache and resolves it again. |
An unknown protocol or an unknown client gives 404.
The list holds, for each client, its protocol, its identity, its organisation number as the registry holds it, where
it came from (the SAML metadata source, or the OpenID Connect backend: properties, configuration, repository or
federation), and when its data expires. A client with no expiry, such as a configured OpenID Connect client, has none:
{
"clients" : [ {
"protocol" : "saml",
"id" : "https://sp.example.com",
"organization-number" : "5566778899",
"source" : "https://md.swedenconnect.se/role/sp.xml",
"expires-at" : "2026-10-08T12:00:00Z"
}, {
"protocol" : "oidc",
"id" : "https://rp.example.com",
"organization-number" : "urn:glue:iso6523:0007:5566778899",
"source" : "federation",
"expires-at" : "2026-10-02T09:14:31Z"
} ]
}
The list shows what the server holds now. For an OpenID Federation client that is the clients in the federation cache, and for an MDQ source the Service Providers that have been asked for.
One client is shown with its marks, which are entity categories for SAML and trust mark types for OpenID Connect, and the path of its metadata:
{
"protocol" : "oidc",
"id" : "https://rp.example.com",
"organization-number" : "urn:glue:iso6523:0007:5566778899",
"marks" : [ "https://id.swedenconnect.se/contract/sc/eid-authorization-system" ],
"source" : "federation",
"expires-at" : "2026-10-02T09:14:31Z",
"metadata" : "/actuator/clients/oidc/metadata?id=https%3A%2F%2Frp.example.com"
}
The answer of an update tells what happened in outcome, with a description in message:
| Outcome | Description |
|---|---|
updated |
The data was fetched again. |
removed |
The OpenID Federation resolver reports the client as not found. It is removed, see Clients added and removed. |
nothing-to-update |
The data does not come from a source that can be updated: a configured OpenID Connect client, a client in a repository, or SAML metadata that is read once from a resource. |
failed |
The update failed, and the answer has HTTP status 502. The data held before is kept. |
{
"protocol" : "oidc",
"id" : "https://rp.example.com",
"outcome" : "updated",
"message" : "Resolved 'https://rp.example.com' again, valid until 2026-10-02T11:02:10Z"
}
A SAML metadata source is updated in the same way as when the scheduled download runs, so the Service Providers that it adds or removes are reported as added and removed.
The update operations change what the server holds and make calls to other services, so the default access of the
endpoint is read-only. Until the deployment grants more, a POST is refused. Grant it with:
management:
endpoint:
clients:
access: unrestricted
As for every Actuator write operation, the request is sent with the content type application/json:
curl -X POST -H 'Content-Type: application/json' \
'https://idp.example.com:8444/actuator/clients/oidc?id=https%3A%2F%2Frp.example.com'
Path: /actuator/info
Reference: Info endpoint
The server adds two entries.
authn-server sums up how the server is set up: the enabled protocols, the SAML entityID, the OpenID Connect
issuer, and the authentication providers with the acr values, the authentication context URIs, that each supports.
With OpenID Federation enabled, it also gives the authority hints and the OpenID Provider’s own trust marks with their
expiry. The issuer is given once, since it is also the federation entity identifier.
"authn-server" : {
"protocols" : [ "saml", "oidc" ],
"saml" : {
"entity-id" : "https://idp.example.com/auth"
},
"oidc" : {
"issuer" : "https://idp.example.com/auth",
"federation" : {
"authority-hints" : [ "https://fed.swedenconnect.se/intermediate" ],
"trust-marks" : [ {
"type" : "https://id.swedenconnect.se/loa/loa3",
"published" : true,
"expires-at" : "2026-12-31T00:00:00Z"
} ]
}
},
"authentication-providers" : [ {
"name" : "bankid",
"acr-values" : [ "http://id.elegnamnden.se/loa/1.0/loa3" ]
} ]
}
client-registry lists the sources of the client registry: each SAML metadata source and each OpenID Connect
backend, with the number of clients it holds and the time of its last update. For a SAML source the last update is
when its metadata last changed; for the federation backend it is when this server instance last resolved a client.
A source that cannot tell how many clients it has, such as an MDQ source, gives no number.
"client-registry" : {
"sources" : [ {
"protocol" : "saml",
"backend" : "saml-metadata",
"name" : "https://md.swedenconnect.se/role/sp.xml",
"clients" : 412,
"last-update" : "2026-10-01T06:00:12Z"
}, {
"protocol" : "oidc",
"backend" : "federation",
"name" : "federation",
"clients" : 37,
"last-update" : "2026-10-01T09:14:31Z"
} ]
}
Path: /actuator/health
Reference: Health endpoint
The server adds the health indicators below, each for an enabled protocol. Spring Boot’s own indicators, such as the
one for Redis, and the indicator of credentials-support for monitored credentials, see
Credential monitoring health endpoint,
are not duplicated. An indicator is turned off with management.health.<key>.enabled: false.
The server adds the status WARNING for a failure where the server still works, for example a metadata download that
failed while the metadata already held is used.
By default WARNING gives HTTP 200, and it is placed between UP and the failing statuses in the status order, so
that a WARNING from one indicator gives WARNING overall unless another one is DOWN or OUT_OF_SERVICE. Both are
Spring Boot settings that the deployment may change:
management:
endpoint:
health:
status:
order: DOWN, OUT_OF_SERVICE, WARNING, UP, UNKNOWN
http-mapping:
down: 503
out-of-service: 503
warning: 503
The order above is the default that the server sets. A deployment that sets http-mapping replaces all of Spring
Boot’s default mappings, so it gives the codes for DOWN and OUT_OF_SERVICE too, as in the example. Without them,
those statuses would give HTTP 200.
Key: saml-metadata
Each SAML metadata source reports whether its latest download succeeded and how old its metadata is.
| Status | When |
|---|---|
UP |
Every source holds metadata and its latest download succeeded. |
WARNING |
The latest download of a source failed. The server keeps using the metadata it has, or the backup file, so it still works, but the metadata gets older. |
OUT_OF_SERVICE |
No source holds a single Service Provider. The server cannot serve any request. |
A download counts as failed also when the server falls back to the metadata it holds or to the backup file. An MDQ source cannot tell how many Service Providers it has, and does not count as empty.
"saml-metadata" : {
"status" : "WARNING",
"details" : {
"sources" : [ {
"name" : "https://md.swedenconnect.se/role/sp.xml",
"last-download" : "2026-10-01T10:00:03Z",
"last-download-successful" : false,
"loaded-at" : "2026-10-01T06:00:12Z",
"age" : "PT3H59M51S",
"service-providers" : 412,
"error" : "HTTP status 503"
} ]
}
}
loaded-at is when the metadata was last downloaded or read successfully, and age is the time since then.
Key: oidc-trust-marks
Present when OpenID Federation is enabled. Each of the OpenID Provider’s own trust mark types, see The trust marks of the OpenID Provider, reports whether a valid trust mark is published, when it expires, when it was last fetched, and, while fetching fails, the number of failed attempts and the latest error.
| Status | When |
|---|---|
UP |
A valid trust mark is published for every type, and the latest fetch or renewal of each succeeded. |
WARNING |
The fetch or renewal of a type failed, or a type has no valid trust mark. |
When the trust marks are kept in Redis, every server instance reports the same.
Key: oidc-federation
The OpenID Federation services that the server calls: the resolver, each trust mark issuer, whether it is called for the OpenID Provider’s own trust marks, for a trust mark that a client is asked to hold, or for a trust mark status check, and each entity whose entity configuration is fetched to find an endpoint that is not configured, see Clients from OpenID Federation. An entity configuration that cannot be fetched or verified, or that does not publish a needed endpoint, counts as a failure.
The health is built from the calls that the server makes, never from calls made by the health check. A resolver
answer that a client is not found is a successful call; any other error answer counts as a failure. Each service
reports the outcome of its latest call and when it was made, its most recent failure with its time, its kind
(error-response or unreachable) and the error, and the number of failed calls since the latest successful one. A
failure is therefore still shown after a later call has succeeded.
| Status | When |
|---|---|
UP |
The latest call to every service succeeded, or no call has been made. |
WARNING |
The latest call to a service failed. |
"oidc-federation" : {
"status" : "UP",
"details" : {
"services" : [ {
"type" : "resolver",
"id" : "https://fed.swedenconnect.se/resolve",
"latest-outcome" : "success",
"latest-call" : "2026-10-01T10:02:44Z",
"failures-since-success" : 0,
"last-failure" : {
"time" : "2026-10-01T09:58:12Z",
"kind" : "unreachable",
"error" : "Failed to make resolve request to https://fed.swedenconnect.se/resolve - Connection refused"
}
} ]
}
}
A resolver is identified by its endpoint, and a trust mark issuer and an entity whose entity configuration is fetched
(type entity-configuration) by their entity identifiers. When the federation cache
is kept in Redis, so is this state, and every server instance reports the same.
The calls are recorded by the HttpFederationClient bean that the auto-configuration declares. An application that
sets up the federation backend of the client registry builds it with that bean, see
The client registry; calls made through a client that the application
creates itself are not seen.
When the server keeps its state in memory, some of it is worth keeping when the server restarts. Give a cache directory:
authn-server:
cache-directory: /var/authn-server/cache
| Property | Description | Default value |
|---|---|---|
authn-server.cache-directory |
A directory where the server keeps state that should survive a restart when it keeps its state in memory. | Nothing is kept |
Without a cache directory nothing is kept, and every start behaves as a first start. The server decides how the directory is organized:
| Path | What it holds |
|---|---|
known-clients.json |
The record of the clients that the server knows, which the server compares with at startup, see Clients added and removed. Written when a client is added or removed. |
oidc/federation-cache.json |
The cache of clients resolved through OpenID Federation. Written a few seconds after a change, and when the server stops. At startup, entries that have expired are dropped. |
oidc/trust-marks/ |
The OpenID Provider’s own trust marks, one file per trust mark type. A stored trust mark is used at startup if it is still valid. |
authn-server.oidc.federation.trust-mark-cache-directory, when set, overrides where the trust marks of the OpenID
Provider are kept.
When state is kept in Redis, see Running several nodes, it survives a
restart there and the cache directory is not used for it. The record of known clients follows
authn-server.storage.type, the federation cache authn-server.oidc.storage.federation-cache and the trust marks
authn-server.oidc.storage.trust-marks.
The server publishes an audit event when a client appears in or disappears from the client registry:
client_added and client_removed. There is one event per
client. Both are system operations, so their principal is the system principal.
A client is added when:
A client is removed when:
A federation client whose cache entry expires and that is resolved again is neither added nor removed.
At startup the clients that the server loads are compared with the record of known clients from before the
restart, which is kept in the cache directory or in Redis. Every Service Provider of
the SAML metadata, every configured OpenID Connect client, and every client of a repository that can list its clients
that was not known gives client_added, and every such client that was known and is no longer there gives
client_removed. The federation clients in the cache that were not known give client_added. A known federation
client that is not in the cache is not removed, since it is only resolved again when it is asked for. Without a
previous record, every client gives client_added once.
With Redis the record of known clients is shared, and each change gives its event once for the whole deployment, not once per server instance.
An MDQ source is queried one Service Provider at a time, so its Service Providers are neither added nor removed.
A deployment that does not want these events in its audit log excludes them in the configuration of its audit
repositories, with spring-audit-support’s audit.repository.exclude-events, or leaves them out of
audit.repository.include-events, see
Configuration:
audit:
repository:
file:
log-file: /var/log/idp/audit.log
exclude-events:
- client_added
- client_removed
Copyright © 2026, Sweden Connect. Licensed under version 2.0 of the Apache License.