I am trying to use pac4j oidc-client to authenticate with login.gov with this security configuration:
oidcConfiguration.setDiscoveryURI("https://idp.int.identitysandbox.gov/.well-known/openid-configuration");
oidcConfiguration.setClientId(clientId);
oidcConfiguration.setUseNonce(true);
oidcConfiguration.setResponseType("code");
oidcConfiguration.setScope("openid");
// Load private key from PEM file
ClassLoader classLoader = getClass().getClassLoader();
File pkFile = new File(classLoader.getResource("private.pem").getFile());
var privateKey = readPKCS8PrivateKey(pkFile);
var privateKeyJwtConfig = new PrivateKeyJWTClientAuthnMethodConfig(JWSAlgorithm.RS256, privateKey);
oidcConfiguration.setPrivateKeyJWTClientAuthnMethodConfig(privateKeyJwtConfig);
oidcConfiguration.addCustomParam("acr_values", "http://idmanagement.gov/ns/assurance/ial/1");
oidcConfiguration.addCustomParam("prompt", "select_account");
oidcConfiguration.addCustomParam("client_assertion_type","urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
oidcConfiguration.setClientAuthenticationMethod(ClientAuthenticationMethod.PRIVATE_KEY_JWT);
oidcConfiguration.setStateGenerator(new RandomValueGenerator(28));
oidcConfiguration.setWithState(true);
oidcConfiguration.setPreferredJwsAlgorithm(JWSAlgorithm.RS256);
oidcConfiguration.setSecret("bogus");
NB: Setting a secret was necessary for the request sent to the token endpoint to include a client_assertion, even though no secret has been set in the login.gov configuration.
The payload of the client_assertion sent by pac4j includes a null iat claim and the token endpoint responds with an error, and an exception is thrown:
JEE PAC4J DEMO 17:53:54.491 [qtp1990828041-45] DEBUG o.p.core.engine.DefaultCallbackLogic - extracted credentials: OidcCredentials(code=e45f8b5b-d039-4c0d-9c75-f6251568fb80, accessToken=null, refreshToken=null, idToken=null)
[WARNING] /callback
org.pac4j.oidc.exceptions.OidcTokenException: Bad token response, error=Client assertion iat must be an integer or floating point Unix timestamp representing a time in the past, description=null, status=400
at org.pac4j.oidc.credentials.authenticator.OidcAuthenticator.executeTokenRequest(OidcAuthenticator.java:120)
at org.pac4j.oidc.credentials.authenticator.OidcAuthenticator.validate(OidcAuthenticator.java:65)
at org.pac4j.core.client.BaseClient.internalValidateCredentials(BaseClient.java:113)
at org.pac4j.core.client.BaseClient.validateCredentials(BaseClient.java:95)
at org.pac4j.core.engine.DefaultCallbackLogic.perform(DefaultCallbackLogic.java:83)
at org.pac4j.jee.filter.CallbackFilter.internalFilter(CallbackFilter.java:63)
at org.pac4j.jee.config.AbstractConfigFilter.doFilter(AbstractConfigFilter.java:92)
at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:210)
at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
at org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:170)
The payload of the client_assertion sent by pac4j includes an iat claim that is null.
{
"sub": "urn:gov:gsa:openidconnect.profiles:sp:sso:doi:quicktime_9996",
"aud": "https://idp.int.identitysandbox.gov/api/openid_connect/token",
"nbf": null,
"iss": "urn:gov:gsa:openidconnect.profiles:sp:sso:doi:quicktime_9996",
"exp": 1717804013,
"iat": null,
"jti": "mspXEErL5LUDuO-x5IUmTYDB679lA0TyYPYIT6d2_xg"
}
What would be the way to make the iat claim generated by pac4j be the current system timestamp instead of a null?
What version of pac4j do you use?