Skip to content

Security configuration

CAS in the cloud LELEU Jérôme edited this page Aug 22, 2022 · 14 revisions

You need to define the security configuration (authentication and authorization mechanisms) in a Config component.

>> Read the documentation of the Config component.

1) It can be built via a configuration factory (org.pac4j.core.config.ConfigFactory):

public class DemoConfigFactory implements ConfigFactory {

    @Override
    public Config build(final Object... parameters) {
        final SAML2ClientConfiguration cfg = new SAML2ClientConfiguration("resource:samlKeystore.jks", "pac4j-demo-passwd", "pac4j-demo-passwd", "resource:testshib-providers.xml");
        cfg.setMaximumAuthenticationLifetime(3600);
        cfg.setServiceProviderEntityId("http://localhost:8080/callback?client_name=SAML2Client");
        cfg.setServiceProviderMetadataPath(new File("sp-metadata.xml").getAbsolutePath());
        final SAML2Client saml2Client = new SAML2Client(cfg);

        final FacebookClient facebookClient = new FacebookClient("145278422258960", "be21409ba8f39b5dae2a7de525484da8");
        final TwitterClient twitterClient = new TwitterClient("CoxUiYwQOSFDReZYdjigBA", "2kAzunH5Btc4gRSaMr7D7MkyoJ5u1VzbOOzE8rBofs");
        final FormClient formClient = new FormClient("http://localhost:8080/loginForm.jsp", new SimpleTestUsernamePasswordAuthenticator());

        ...

        final Clients clients = new Clients("http://localhost:8080/callback", oidcClient, saml2Client, facebookClient,
                twitterClient, formClient, indirectBasicAuthClient, casClient, parameterClient,
                directBasicAuthClient, new AnonymousClient(), casProxy);

        final Config config = new Config(clients);
        config.addAuthorizer("admin", new RequireAnyRoleAuthorizer<>("ROLE_ADMIN"));
        config.addAuthorizer("custom", new CustomAuthorizer());
        config.addAuthorizer("mustBeAnon", new IsAnonymousAuthorizer<>("/?mustBeAnon"));
        config.addAuthorizer("mustBeAuth", new IsAuthenticatedAuthorizer<>("/?mustBeAuth"));
        config.addMatcher("excludedPath", new PathMatcher().excludeRegex("^/facebook/notprotected\\.jsp$"));
        return config;
    }
}

if the configFactory servlet parameter is used:

   <init-param>
      <param-name>configFactory</param-name>
      <param-value>org.pac4j.demo.jee.DemoConfigFactory</param-value>
   </init-param>

Notice that this configFactory servlet parameter only needs to be defined for one filter as the configuration will be shared between all filters.

See a full example here.

2) Or produced via CDI (JEE):

@Dependent
public class SecurityConfig {

    @Produces @ApplicationScoped
    private Config buildConfiguration() {
        logger.debug("building Security configuration...");

        final OidcConfiguration oidcConfiguration = new OidcConfiguration();
        oidcConfiguration.setClientId("167480702619-8e1lo80dnu8bpk3k0lvvj27noin97vu9.apps.googleusercontent.com");
        oidcConfiguration.setSecret("MhMme_Ik6IH2JMnAT6MFIfee");
        oidcConfiguration.setUseNonce(true);
        oidcConfiguration.addCustomParam("prompt", "consent");
        final GoogleOidcClient oidcClient = new GoogleOidcClient(oidcConfiguration);
        oidcClient.setAuthorizationGenerator((ctx, profile) -> { profile.addRole("ROLE_ADMIN"); return profile; });

        final FormClient jsfFormClient = new FormClient(
                "http://localhost:8080/jsfLoginForm.action",
                new SimpleTestUsernamePasswordAuthenticator()
        );
        jsfFormClient.setName("jsfFormClient");

        final IndirectBasicAuthClient indirectBasicAuthClient = new IndirectBasicAuthClient(new SimpleTestUsernamePasswordAuthenticator());

        final CasConfiguration configuration = new CasConfiguration("http://localhost:8888/cas/login");
        final CasClient casClient = new CasClient(configuration);

        final List<SignatureConfiguration> signatures = new ArrayList<>();
        signatures.add(new SecretSignatureConfiguration(Constants.JWT_SALT));
        ParameterClient parameterClient = new ParameterClient("token", new JwtAuthenticator(signatures));
        parameterClient.setSupportGetRequest(true);
        parameterClient.setSupportPostRequest(false);

        final DirectBasicAuthClient directBasicAuthClient = new DirectBasicAuthClient(new SimpleTestUsernamePasswordAuthenticator());

        ...

        final Clients clients = new Clients(
                "http://localhost:8080/callback",
                oidcClient,
                formClient,
                jsfFormClient,
                saml2Client, facebookClient, twitterClient, indirectBasicAuthClient, casClient,
                parameterClient, directBasicAuthClient, new AnonymousClient()
        );

        return new Config(clients);
    }
}

See a full example here.

3) Or it can be defined in a Spring way

Example of Spring context:

<bean id="roleAdminAuthGenerator" class="org.pac4j.demo.spring.RoleAdminAuthGenerator" />

<bean id="googleConfigurationClient" class="org.pac4j.oidc.config.OidcConfiguration">
    <property name="clientId" value="167480702619-8e1lo80dnu8bpk3k0lvvj27noin97vu9.apps.googleusercontent.com" />
    <property name="secret" value="MhMme_Ik6IH2JMnAT6MFIfee" />
</bean>
<bean id="googleOidcClient" class="org.pac4j.oidc.client.GoogleOidcClient">
    <constructor-arg ref="googleConfigurationClient"/>
    <property name="authorizationGenerator" ref="roleAdminAuthGenerator" />
</bean>

<bean id="samlConfig" class="org.pac4j.saml.client.SAML2ClientConfiguration">
    <property name="keystorePath" value="resource:samlKeystore.jks" />
    <property name="keystorePassword" value="pac4j-demo-passwd" />
    <property name="privateKeyPassword" value="pac4j-demo-passwd" />
    <property name="identityProviderMetadataPath" value="resource:metadata-okta.xml" />
    <property name="maximumAuthenticationLifetime" value="3600" />
    <property name="serviceProviderEntityId" value="http://localhost:8080/callback?client_name=SAML2Client" />
    <property name="serviceProviderMetadataPath" value="sp-metadata.xml" />
</bean>
<bean id="samlClient" class="org.pac4j.saml.client.SAML2Client">
    <constructor-arg name="configuration" ref="samlConfig" />
</bean>

...

<bean id="clients" class="org.pac4j.core.client.Clients">
    <property name="callbackUrl" value="http://localhost:8080/callback" />
    <property name="clients">
        <list>
            <ref bean="googleOidcClient" />
            <ref bean="facebookClient" />
            <ref bean="twitterClient" />
            <ref bean="googleClient" />
            <ref bean="mitreIdClient" />
            <ref bean="formClient" />
            <ref bean="indirectBasicAuthClient" />
            <ref bean="casClient" />
            <ref bean="samlClient" />
            <ref bean="parameterClient" />
            <ref bean="directBasicAuthClient" />
            <ref bean="anonymousClient" />
        </list>
    </property>
</bean>

<bean id="config" class="org.pac4j.core.config.Config">
    <property name="clients" ref="clients" />
    <property name="authorizers">
        <map>
            <entry key="admin">
                <bean class="org.pac4j.core.authorization.authorizer.RequireAnyRoleAuthorizer">
                    <constructor-arg name="roles" value="ROLE_ADMIN" />
                </bean>
            </entry>
            <entry key="custom">
                <bean class="org.pac4j.demo.spring.CustomAuthorizer" />
            </entry>
        </map>
    </property>
    <property name="matchers">
        <map>
            <entry key="excludedPath">
                <bean class="org.pac4j.core.matching.PathMatcher">
                    <constructor-arg name="regexpPath" value="^/facebook/notprotected\.jsp$" />
                </bean>
            </entry>
        </map>
    </property>
</bean>

Example of a Java class configuration:

@onfiguration
public class Pac4jConfig {

    ...

    @Bean
    public Config config() {
        ...

        final FacebookClient facebookClient = new FacebookClient("145278422258960", "be21409ba8f39b5dae2a7de525484da8");
        final TwitterClient twitterClient = new TwitterClient("CoxUiYwQOSFDReZYdjigBA",
                "2kAzunH5Btc4gRSaMr7D7MkyoJ5u1VzbOOzE8rBofs");

        final SimpleTestUsernamePasswordAuthenticator simpleTestUsernamePasswordAuthenticator = new SimpleTestUsernamePasswordAuthenticator();
        final FormClient formClient = new FormClient("http://localhost:8080/loginForm.jsp", simpleTestUsernamePasswordAuthenticator);
        final IndirectBasicAuthClient indirectBasicAuthClient = new IndirectBasicAuthClient(simpleTestUsernamePasswordAuthenticator);

        final CasConfiguration casConfiguration = new CasConfiguration("https://casserverpac4j.herokuapp.com/login");
        final CasClient casClient = new CasClient(casConfiguration);

        ParameterClient parameterClient = new ParameterClient("token", new JwtAuthenticator(new SecretSignatureConfiguration(salt), new SecretEncryptionConfiguration(salt)));
        parameterClient.setSupportGetRequest(true);
        parameterClient.setSupportPostRequest(false);

        final DirectBasicAuthClient directBasicAuthClient = new DirectBasicAuthClient(simpleTestUsernamePasswordAuthenticator);

        final AnonymousClient anonymousClient = new AnonymousClient();

        final Clients clients = new Clients("http://localhost:8080/callback", oidcClient, saml2Client, facebookClient,
                twitterClient, formClient, indirectBasicAuthClient, casClient, parameterClient, directBasicAuthClient, anonymousClient);

        final Config config = new Config(clients);
        config.addAuthorizer("admin", new RequireAnyRoleAuthorizer("ROLE_ADMIN"));
        config.addAuthorizer("custom", new CustomAuthorizer());
        config.addMatcher("excludedPath", new PathMatcher().excludeRegex("^/facebook/notprotected\\.html$"));
        return config;
    }
}

See a full example here.

4) Or it can be defined in a shiro.ini file for a Shiro webapp:

[main]
############################################################################
# CONFIG:
############################################################################
oidcConfig = org.pac4j.oidc.config.OidcConfiguration
oidcConfig.clientId = 167480702619-8e1lo80dnu8bpk3k0lvvj27noin97vu9.apps.googleusercontent.com
oidcConfig.secret =MhMme_Ik6IH2JMnAT6MFIfee
oidcConfig.useNonce = true

googleOidClient = org.pac4j.oidc.client.GoogleOidcClient
googleOidClient.configuration = $oidcConfig
googleOidClient.authorizationGenerator = $roleAdminAuthGenerator

...

clients.callbackUrl = http://localhost:8080/callback
clients.clients = $googleOidClient,$saml2Client,$directBasicAuthClient

See a full example here