Integrating a minimal FormClient auth System into My Java/Play 2.5 App

223 views
Skip to first unread message

chris.ca...@gmail.com

unread,
Apr 18, 2018, 5:43:58 PM4/18/18
to Pac4j users mailing list
I've been working on integrating Pac4j into my Play 2.5 Java app. 

I've got a basic login form and a custom authenticator, which works great.  I can login and it will redirect me to the page I need.  Trouble comes when I enable the security rules.

pac4j.security {
  rules = [
      {"/loginForm" = {
              authorizers = "_anonymous_"
          }
      }
      {"/callback.*" = {
              authorizers = "_anonymous_"
          }
      }
      {"/assets/.*" = {
              authorizers = "_anonymous_"
          }
      }
    {"/introPage" = {
              clients = "FormClient"
              authorizers = "_authenticated_"
        }
    }
    {".*" = {
            authorizers = "_authenticated_"
            clients = "FormClient"
        }
    }
  ]
}

When I enable, for instance, a rule on the /introPage it ALWAYS bounces me back to the login form, as if it's not authenticated.  Any ideas where to look or what to share here for further troubleshooting?

Here's the relevant parts of my build.sbt:

 "org.pac4j" % "play-pac4j" % "3.0.1",
  "org.pac4j" % "pac4j-http" % "2.0.0",
  "be.objectify" %% "deadbolt-java" % "2.4.0",


Here's my SecurityModule, whittled down to the bare minimum:

public class SecurityModule extends AbstractModule {
     public final static String JWT_SALT = "12345678901234567890123456789012";

        private final Configuration configuration;

        private static class MyPac4jRoleHandler implements Pac4jRoleHandler { }

        public SecurityModule(final Environment environment, final Configuration configuration) {
            this.configuration = configuration;
        }

        @Override
        protected void configure() {
            System.out.println("configure()");
            bind(HandlerCache.class).to(Pac4jHandlerCache.class);

            bind(Pac4jRoleHandler.class).to(MyPac4jRoleHandler.class);
            final PlayCacheSessionStore playCacheSessionStore = new PlayCacheSessionStore(getProvider(CacheApi.class));
            bind(PlaySessionStore.class).toInstance(playCacheSessionStore);

//            final String fbId = configuration.getString("fbId");
//            final String fbSecret = configuration.getString("fbSecret");
            final String baseUrl = "http://localhost:9000";
            System.out.println("baseurl=" + baseUrl);

//            final FacebookClient facebookClient = new FacebookClient(fbId, fbSecret);
//            final TwitterClient twitterClient = new TwitterClient("HVSQGAw2XmiwcKOTvZFbQ", "FSiO9G9VRR4KCuksky0kgGuo8gAVndYymr4Nl7qc8AA");
            final FormClient formClient = new FormClient(baseUrl + "/loginForm", new DiagnosticGUIAuthenticator());
//            final IndirectBasicAuthClient indirectBasicAuthClient = new IndirectBasicAuthClient(new DiagnosticGUIAuthenticator());
//            final IndirectBasicAuthClient indirectBasicAuthClient = new IndirectBasicAuthClient(new SimpleTestUsernamePasswordAuthenticator());

//            final CasConfiguration casConfiguration = new CasConfiguration("http://localhost:8888/cas/login");
//            final CasProxyReceptor casProxyReceptor = new CasProxyReceptor();
//            casConfiguration.setProxyReceptor(casProxyReceptor);
//            final CasClient casClient = new CasClient(casConfiguration);

//            final SAML2ClientConfiguration cfg = new SAML2ClientConfiguration("resource:samlKeystore.jks", "pac4j-demo-passwd", "pac4j-demo-passwd", "resource:openidp-feide.xml");
//            cfg.setMaximumAuthenticationLifetime(3600);
//            cfg.setServiceProviderEntityId("urn:mace:saml:pac4j.org");
//            cfg.setServiceProviderMetadataPath(new File("target", "sp-metadata.xml").getAbsolutePath());
//            final SAML2Client saml2Client = new SAML2Client(cfg);

//            final OidcConfiguration oidcConfiguration = new OidcConfiguration();
//            oidcConfiguration.setClientId("343992089165-i1es0qvej18asl33mvlbeq750i3ko32k.apps.googleusercontent.com");
//            oidcConfiguration.setSecret("unXK_RSCbCXLTic2JACTiAo9");
//            oidcConfiguration.setDiscoveryURI("https://accounts.google.com/.well-known/openid-configuration");
//            oidcConfiguration.addCustomParam("prompt", "consent");
//            final OidcClient oidcClient = new OidcClient(oidcConfiguration);
//            oidcClient.addAuthorizationGenerator((ctx, profile) -> { profile.addRole("ROLE_ADMIN"); return profile; });

//            final ParameterClient parameterClient = new ParameterClient("token",
//                    new JwtAuthenticator(new SecretSignatureConfiguration(JWT_SALT)));
//            parameterClient.setSupportGetRequest(true);
//            parameterClient.setSupportPostRequest(false);

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

            final Clients clients = new Clients(baseUrl + "/callback", formClient, new AnonymousClient());

            final Config config = new Config(clients);
//            config.addAuthorizer("admin", new RequireAnyRoleAuthorizer<>("ROLE_ADMIN"));
            config.addAuthorizer("custom", new CustomAuthorizer());
//            config.setHttpActionAdapter( new DefaultHttpActionAdapter());
            config.setHttpActionAdapter(new DiagnosticGuiHttpActionAdapter());
            bind(Config.class).toInstance(config);

            final CallbackController callbackController = new CallbackController();
            callbackController.setDefaultUrl("/");
            bind(CallbackController.class).toInstance(callbackController);

            final LogoutController logoutController = new LogoutController();
            logoutController.setDefaultUrl("/?defaulturlafterlogout");
            bind(LogoutController.class).toInstance(logoutController);
        }
//    @Override
//    protected void configure() {
////        bind(HandlerCache.class).to(Pac4jHandlerCache.class);
////
//////        bind(Pac4jRoleHandler.class).to(MyPac4jRoleHandler.class);
////        final PlayCacheSessionStore playCacheSessionStore = new PlayCacheSessionStore(getProvider(SyncCacheApi.class));
////        //bind(PlaySessionStore.class).toInstance(playCacheSessionStore);
////        bind(PlaySessionStore.class).to(PlayCacheSessionStore.class);
////
////        // callback
////        final CallbackController callbackController = new CallbackController();
////        callbackController.setDefaultUrl("/");
////        callbackController.setMultiProfile(true);
////        bind(CallbackController.class).toInstance(callbackController);
////
////        // logout
////        final LogoutController logoutController = new LogoutController();
////        logoutController.setDefaultUrl("/?defaulturlafterlogout");
////        logoutController.setDestroySession(true);
////        bind(LogoutController.class).toInstance(logoutController);
////        bind(HandlerCache.class).to(Pac4jHandlerCache.class);
////
//////        bind(Pac4jRoleHandler.class).to(MyPac4jRoleHandler.class);
////        final PlayCacheSessionStore playCacheSessionStore = new PlayCacheSessionStore(getProvider(SyncCacheApi.class));
////        //bind(PlaySessionStore.class).toInstance(playCacheSessionStore);
////        bind(PlaySessionStore.class).to(PlayCacheSessionStore.class);
////
////        // callback
////        final CallbackController callbackController = new CallbackController();
////        callbackController.setDefaultUrl("/");
////        callbackController.setMultiProfile(true);
////        bind(CallbackController.class).toInstance(callbackController);
////
////        // logout
////        final LogoutController logoutController = new LogoutController();
////        logoutController.setDefaultUrl("/?defaulturlafterlogout");
////        //logoutController.setDestroySession(true);
////        bind(LogoutController.class).toInstance(logoutController);
//    }
//   
     @Provides
     protected FormClient provideFormClient() {
         System.out.println("providing form client");
         return new FormClient("http://127.0.0.1" + "/loginForm", new DiagnosticGUIAuthenticator());//new SimpleTestUsernamePasswordAuthenticator());
     }
////     
////     @Provides Config provideConfig(FormClient formClient) {
////         final Clients clients = new Clients("", formClient);
////         final Config config = new Config(clients);
////         return config;
////         
////     }

}

Jérôme LELEU

unread,
Apr 19, 2018, 10:46:06 AM4/19/18
to chris.ca...@gmail.com, Pac4j users mailing list
Hi,

Can you enable DEBUG logs on org.pac4j and copy/paste them here?
Thanks.
Best regards,
Jérôme


--
You received this message because you are subscribed to the Google Groups "Pac4j users mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

chris.ca...@gmail.com

unread,
Apr 19, 2018, 11:58:40 AM4/19/18
to Pac4j users mailing list
Hi Jérôme,

Thanks for getting back to me.  This may be a dumb question but how would I enable these logs?  I looked through the pac4j-java code and did see a reference to slf4j.  Do you know of a good way to do this while using "sbt run" to run your app?

Thanks,
Chris
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users...@googlegroups.com.

chris.ca...@gmail.com

unread,
Apr 19, 2018, 1:30:40 PM4/19/18
to Pac4j users mailing list

Figured it out, updated the logback.xml file in my play framework conf.  Here's some logs from a login attempt.


[debug] o.p.p.f.SecurityFilter - No authentication needed for /callback?username=abc&password=abc&submit=Submit&client_name=FormClient
[debug] o.p.c.e.DefaultCallbackLogic - === CALLBACK ===
[debug] o.p.c.e.DefaultCallbackLogic - client: #FormClient# | callbackUrl: http://localhost:9000/callback?client_name=FormClient | name: FormClient | loginUrl: http://localhost:9000/loginForm | usernameParameter: username | passwordParameter: password | redirectActionBuilder: org.pac4j.http.client.indirect.FormClient$$Lambda$45/1615770347@3652d32 | extractor: org.pac4j.core.credentials.extractor.FormExtractor@5e8ca18a | authenticator: security.DiagnosticGUIAuthenticator@3ea0c3e8 | profileCreator: org.pac4j.core.profile.creator.AuthenticatorProfileCreator@66391bde |
[debug] o.p.h.c.i.FormClient - usernamePasswordCredentials: #UsernamePasswordCredentials# | username: abc | password: [PROTECTED] | clientName: FormClient |
confFile=C:\MentorGraphics_Data\UtilitiesData\configurations\diagnosticSettings\diagConf.xml
configuredUsername=abc
configuredPassword=abc
diagnosticGuiAuthenticator: validate()
username='abc'
password='abc'
[debug] o.p.c.e.DefaultCallbackLogic - credentials: #UsernamePasswordCredentials# | username: abc | password: [PROTECTED] | clientName: FormClient |
[debug] o.p.h.c.i.FormClient - credentials : #UsernamePasswordCredentials# | username: abc | password: [PROTECTED] | clientName: FormClient |
[debug] o.p.h.c.i.FormClient - profile: null
[debug] o.p.c.e.DefaultCallbackLogic - profile: null
[debug] o.p.c.e.DefaultCallbackLogic - redirectUrl: http://localhost:9000/
DiagnosticGuiHttpActionAdapter: DEFAULT - code=302
[debug] c.DiagnosticGuiHttpActionAdapter - requires HTTP action: 302
[debug] o.p.p.f.SecurityFilter - Authentication needed for /
[debug] o.p.c.e.DefaultSecurityLogic - === SECURITY ===
[debug] o.p.c.e.DefaultSecurityLogic - url: http://localhost:9000/
[debug] o.p.c.e.DefaultSecurityLogic - matchers: null
[debug] o.p.c.e.DefaultSecurityLogic - clients: FormClient
[debug] o.p.c.e.DefaultSecurityLogic - currentClients: [#FormClient# | callbackUrl: http://localhost:9000/callback?client_name=FormClient | name: FormClient | loginUrl: http://localhost:9000/loginForm | usernameParameter: username | passwordParameter: password | redirectActionBuilder: org.pac4j.http.client.indirect.FormClient$$Lambda$45/1615770347@3652d32 | extractor: org.pac4j.core.credentials.extractor.FormExtractor@5e8ca18a | authenticator: security.DiagnosticGUIAuthenticator@3ea0c3e8 | profileCreator: org.pac4j.core.profile.creator.AuthenticatorProfileCreator@66391bde |]
[debug] o.p.c.e.DefaultSecurityLogic - loadProfilesFromSession: true
[debug] o.p.c.e.DefaultSecurityLogic - profiles: []
[debug] o.p.c.e.DefaultSecurityLogic - Starting authentication
[debug] o.p.c.e.DefaultSecurityLogic - requestedUrl: http://localhost:9000/
DiagnosticGuiHttpActionAdapter: DEFAULT - code=302
[debug] c.DiagnosticGuiHttpActionAdapter - requires HTTP action: 302
[info] o.p.p.f.SecurityFilter - Authentication failed for / with clients FormClient and authorizers null. Authentication response code 303.
[debug] o.p.p.f.SecurityFilter - No authentication needed for /loginForm
formClient.getCallbackUrl()=http://localhost:9000/callback?client_name=FormClient
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/jquery-3.2.1.min.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/bootstrap.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/moment.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/bootstrap-tour.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/bootstrap-datetimepicker.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/jquery.ba-hashchange.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/jquery-ui-1.10.4.custom.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/stylesheets/flatly-bootstrap.css
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/stylesheets/bootstrap-tour.css
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/stylesheets/bootstrap-datetimepicker.css
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/stylesheets/main.css
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/stylesheets/xmlDisplay.css
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/stylesheets/collectlogs.css
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/stylesheets/serverActionsBar.css
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/stylesheets/configWorkflow.css
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/stylesheets/vis.css
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/stylesheets/c3.css
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/stylesheets/jquery-ui.css
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/jquery-ui-1.11.2.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/jquery.form.min.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/vis.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/c3.min.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/d3.min.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/underscore-min.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/pubsub.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/sutgui.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/masterOrNodeObject.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/masterOrNodeObjectsList.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/xmlTreeDefaultValue.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/xmlItemTreeMatcher.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/xmlItemTreeGenerator.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/xmlDisplay.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/xmlActions.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/collectlogs.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/logoptionsdropdown.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/serverActionsBar.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/configDiffTable.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/sha1.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/javascripts/memory_leak_checker.js
[debug] o.p.p.f.SecurityFilter - No authentication needed for /assets/images/bg-logo-white.png

Jérôme LELEU

unread,
Apr 20, 2018, 8:45:18 AM4/20/18
to chris.ca...@gmail.com, Pac4j users mailing list
Hi,

In Play, we use logback for logging, so this file must be used: https://github.com/pac4j/play-pac4j-java-demo/blob/master/conf/logback.xml#L15 

Thanks.
Best regards,
Jérôme


To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users+unsubscribe@googlegroups.com.

Chris Case

unread,
Apr 20, 2018, 10:47:29 AM4/20/18
to Jérôme LELEU, Pac4j users mailing list
Ok, here's an attached logfile.  It includes a few attempts.  Some with valid and some with invalid credentials.  All were bounced back to the login form.  I notice that profile is showing up as null.  I'm digging in to see what I can find out but if you have any insights I'd love to hear them.
auth.log

Jérôme LELEU

unread,
Apr 20, 2018, 10:54:53 AM4/20/18
to Chris Case, Pac4j users mailing list
Hi,

Yes, the profile is null so there is no authenticated profile.

I think you don't save the authenticated profile in the credentials as should do any Authenticator using the AuthenticatorProfileCreator (by default).

So you should have: credentials.setUserProfile(profile) in your Authenticator.

Thanks.
Best regards,
Jérôme

chris.ca...@gmail.com

unread,
Apr 20, 2018, 12:16:06 PM4/20/18
to Pac4j users mailing list
I do believe that this did indeed resolve my issue.  Thanks Jérôme!  I was pretty well stuck there for a good while.

Regards,
Chris
Reply all
Reply to author
Forward
0 new messages