Search code examples
openid-connectpac4j

Using pac4j token request for login.gov fails because client_assertion includes null iat claim


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?


Solution

  • What version of pac4j do you use?