OpenID Connect / Federation (v6.5)
See also:
▸ Basic configuration and OIDC clients
▸ Advanced configuration settings
Since v6.4.0, pac4j supports the OpenID Connect Federation v1.0. It has been tested with Connect2id v19.8.
The OIDC client is considered to have the federation enabled if the property federation.targetOp is not blank.
1) Federation endpoint
To enable the federation endpoint at the RP (application) level, you need to configure a set of private/public keys:
- either via a keystore (like for the SAML protocol):
oidcConfig.getFederation().getKeystore().setKeystorePath("file:./metadata/oidcfede.keystore");
oidcConfig.getFederation().getKeystore().setKeystorePassword("changeit");
oidcConfig.getFederation().getKeystore().setPrivateKeyPassword("changeit");
You have several additional settings in the KeystoreProperties.
- or via a JWKS:
oidcConfig.getFederation().getJwks().setJwksPath("file:./metadata/oidcfede.jwks");
oidcConfig.getFederation().getJwks().setKid("mykeyoidcfede26");
In both cases (keystore or JWKS), if it doesn’t exist, it will be created (for a file setting).
OidcFederationProperties controls both the RP entity statement generated by the federation endpoint and the federation-based OP resolution.
Available properties are:
keystore(KeystoreProperties): keystore-based signing material for the entity statement. By default, pac4j sets the certificate prefix tooidcfede-signing-cert, the certificate validity to 1 year, and uses a filesystem keystore generator.jwks(JwksProperties): JWKS-based signing material for the entity statement. If both JWKS and keystore are configured, JWKS is used first.entityConfigurationGenerator(EntityConfigurationGenerator): component used by the endpoint to generate the entity configuration. If not set,OidcClientassignsDefaultEntityConfigurationGenerator.validityInDays(int, default:90): validity duration of the generated entity statement (exp - iat).entityId(String, optional): entity identifier used asiss,sub, andaudin the generated statement. If not set, the callback URL is used.applicationType(String, default:web): value of theapplication_typeRP metadata claim (webornative).responseTypes(List<String>, default:["code"]): value of theresponse_typesRP metadata claim.grantTypes(List<String>, default:["authorization_code"]): value of thegrant_typesRP metadata claim.scopes(List<String>, default:["openid", "email", "profile"]): value of thescopeRP metadata claim (serialized as a space-separated string).clientName(String, optional): value of theclient_nameRP metadata claim.contacts(List<String>, default: empty list): value of thecontactsRP metadata claim when at least one contact is provided.trustAnchors(List<OidcTrustAnchorProperties>, default: empty list): trust anchors used to resolve trust chains (issuerandjwksResourcefor each anchor).targetOp(String): OP entity identifier to resolve via federation. When set, federation mode is used instead of discovery URI resolution.secretExportFile(String): the file where to save a received secret during an explicit registration.
At least one signing source must be configured with a resource/path (jwks or keystore) to generate the entity configuration.
You must use the EntityConfigurationGenerator component to retrieve the entity configuration:
Spring Boot example:
@RequestMapping(value = "/.well-known/openid-federation", produces = DefaultEntityConfigurationGenerator.CONTENT_TYPE)
@ResponseBody
public String oidcFederation() throws HttpAction {
val oidcClient = (OidcClient) config.getClients().findClient("OidcClient").get();
return oidcClient.getConfiguration().getFederation().getEntityConfigurationGenerator().generate();
}
2) Using trust anchors
When using federation, you must not define the discoveryURI. You must only define the trust anchors and the target entity (the OP) in the federation space.
val federation = oidcConfig.getFederation();
federation.setTargetOp("http://localhost:8080/op");
val trust = new OidcTrustAnchorProperties();
trust.setTaIssuer("http://localhost:8081/ta");
trust.setTaJwksUrl("http://localhost:8081/ta/jwks.json");
federation.getTrustAnchors().add(trust);
The federation metadata resolver performs a blocking load on first use, then refreshes metadata in the background when the trust chain expires.
3) Explicit / automatic client registration
If the RP is not yet registered and its clientId is left blank, pac4j supports both client registration modes and validates them against the OP metadata.
Priority is given to automatic mode if supported by the OP. In this case, the entity statement is sent via the client_assertion parameter in the authorization request URL.
Otherwise, if only explicit mode is supported and the federation_registration_endpoint exists, pac4j calls it to retrieve a client_id (and optionally a client_secret).
The client_id is displayed in the logs as follows: /!\ Explicit registration of the client 'http://rp' returned id: [XXX]. This information will not be repeated. You MUST manually add this value to your configuration before the next application startup!.
The client_secret is saved in the secretExportFile and must also be manually added to the configuration: /!\ The received secret has been saved into the file: YYY.