I use Pac4J to authenticate users via OpenID Connect (OIDC). Note: We don't use Pac4J as a framework to do our session handling, but just as a library for OIDC. I authenticate the callback like this:
Optional<Credentials> credentials = client.getCredentials(context, sessionStore);
return client.getUserProfile(credentials.orElse(null), context, sessionStore)
.map(CommonProfile.class::cast)
.orElse(null);
Facebook is configured with this discovery URL: https://www.facebook.com/.well-known/openid-configuration/
Now the authentication fails, because we don't have a token endpoint. As described in this guide, the tokens are not supposed to be validated with an endpoint, but directly as JWT: https://developers.facebook.com/docs/facebook-login/limited-login/token/validating
How can I configure Pac4J to work with Facebook's implementation of OpenID Connect that seems to deviate from the standard? Is this possible with standard configuration options of Pac4J like OidcConfiguration
and OIDCProviderMetadata
? Or do we have to create custom implementations of some of the Pac4J interfaces? Or is this not possible at all?
The reasons why the Oidc Login via Facebook does not work regularly are the following:
We implemented the Facebook Login with a configuration page, where token endpoint, scope, useNonce, pkceMethod and client authentication method can be set manually. The data is added to the oidcConfiguration
and thus, to the oidcClient
.
When configured properly, the code looks like the following:
OidcConfiguration facebookOidcConfiguration = new OidcConfiguration();
final var providerMetadata = new OIDCProviderMetadata(
new Issuer("https://www.facebook.com"),
Collections.singletonList(SubjectType.PAIRWISE),
URI.create("https://www.facebook.com/.well-known/oauth/openid/jwks/"));
providerMetadata.setTokenEndpointURI(URI.create("https://graph.facebook.com/v17.0/oauth/access_token"));
//set more providerMetadata here
facebookConfiguration.setProviderMetadata(providerMetadata);
facebookConfiguration.setScope("openid email public_profile");
facebookConfiguration.setUseNonce(true);
facebookConfiguration.setPkceMethod(CodeChallengeMethod.PLAIN);
facebookConfiguration.setClientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST);
//set more configuration data here
OidcClient facebookClient = new OidcClient(facebookOidcConfiguration);
If you want, you can create a class FacebookConfiguration
(inheriting from OidcConfiguration
) to perform the described steps, but it is not required.