Using a web application as SP with vertx and pac4j with SAML does not logout correctly

44 Views Asked by At

I am starting to use verxt and pac4j. I am creating a web application with vertx, pac4j and pac4j-vertx to authenticate users with the SAML protocol. The web application acts as SP and as IdP I am using simplesamlphp.

My problem is that when I logout the user in the SP, he can still access the protected resources, instead of redoing the SAML authentication process. The SAML logout flow with the IdP completes correctly and the user logout in the IdP, I have checked this using the google-chrome SAML-tracer extension.

The application consists of two static html pages: a login page called login.html which is accessed at the url /login (this path is not protected as it is the index for logging in). And another resource called msg.html which is accessed with the path /msg.html. The msg.html is a protected resource which users must first authenticate to be able to access it.

When the user logs out in the SP he can still access the /msg.html resource afterwards, instead of redoing the SAML authentication process. Does anyone know why this happens and how to solve it so that the user can't access the resource after logging out in the SP and the user has to redoing the SAML authentication process? Can't vertx and pac4j be used with static html pages?

The verxt code with pac4j that I am using for SAML authentication with the IdP is as follows:

public class MainVerticle extends AbstractVerticle {

  @Override
  public void start(Promise<Void> startPromise) throws Exception {

    HttpServerOptions serverOptions = new HttpServerOptions().setMaxFormAttributeSize(65536);
    HttpServer server = vertx.createHttpServer(serverOptions);
    Router router = Router.router(vertx);
    LocalSessionStore vertxSessionStore = LocalSessionStore.create(vertx);
    SessionStore sessionStore = new VertxSessionStore(vertxSessionStore);
    Pac4jAuthProvider authProvider = new Pac4jAuthProvider();
    SessionHandler sessionHandler = SessionHandler.create(vertxSessionStore);

    router.get("/login").handler(StaticHandler.create("src/main/resources/static/login.html"));

    SAML2Client saml2Client = this.saml2Client();
    Config config = new Config("http://localhost:8888/callback",saml2Client);

    router.route().handler(sessionHandler);
    
    SecurityHandlerOptions options = new SecurityHandlerOptions().setClients("SAML2Client");
    router.route("/msg.html").handler(new SecurityHandler(vertx, sessionStore, config, authProvider,options));
    router.get("/msg.html").handler(rc ->{
      rc.response().putHeader(CONTENT_TYPE, TEXT_HTML);
      rc.next();
    });
    router.get("/msg.html").handler(StaticHandler.create("src/main/resources/static/msg.html"));

    CallbackHandlerOptions callbackHandlerOptions = new CallbackHandlerOptions()
                .setDefaultUrl("/")
                .setMultiProfile(true);
    CallbackHandler callbackHandler = new CallbackHandler(vertx, sessionStore, config, callbackHandlerOptions);
    router.get("/callback").handler(callbackHandler);
    router.post("/callback").handler(BodyHandler.create().setMergeFormAttributes(true));
    router.post("/callback").handler(callbackHandler);

    router.get("/logout").handler(SingleLogouthandler(vertx, config, sessionStore));

    server.requestHandler(router).listen(8888, http -> {
      if (http.succeeded()) {
            startPromise.complete();
            System.out.println("HTTP server started on port 8888");
          } else {
            startPromise.fail(http.cause());
          }
    });
  }

  private SAML2Client saml2Client(){
    SAML2Configuration cfg = new SAML2Configuration("samlConfig/samlKeystore.jks", 
                                    "pac4j-demo-passwd", 
                                    "pac4j-demo-passwd", 
                                    "samlConfig/idp-metadata.xml");

    cfg.setResponseBindingType(SAMLConstants.SAML2_POST_BINDING_URI);
    cfg.setServiceProviderEntityId("http://localhost:8888/callback?client_name=SAML2Client");
    cfg.setServiceProviderMetadataPath(new File("target", "sp-metadata.xml").getAbsolutePath());
    return new SAML2Client(cfg);
  }

  private Handler<RoutingContext> SingleLogouthandler(Vertx vertx, Config config, SessionStore sessionStore){
    LogoutHandlerOptions logoutOptions = new LogoutHandlerOptions()
        .setCentralLogout(true)
        .setLocalLogout(true)
        .setDefaultUrl("http://localhost:8888/login")
    return new LogoutHandler(vertx, sessionStore, logoutOptions, config);
  }

}

The html code for the login is as follows:

<!DOCTYPE html>
<html>
<head>
    <title>Login page</title>
</head>
<body>
    <h2>Log in</h2>
    <a href="/msg.html">Login using SAML</a><br/>
</body>
</html>

The code of the /msg.html resource is as follows:

<!DOCTYPE html>
<html>
<head>
    <title>Login Successful</title>
</head>
<body>
    <h1>Login Successful</h1>
    <a href="/logout">local logout</a>
</body>
</html>

1

There are 1 best solutions below

3
jleleu On

Your configuration looks good. You should turn on DEBUG logs on the org.pac4j package to see what occurs after the logout when you call again a protected page. Did you take a look at the https://github.com/pac4j/vertx-pac4j-demo as its logout works?