Community
Participate
Working Groups
Build Identifier: jetty-8.0.1.v20110908 When I configured Jetty 8 to use JASPI, it does not works. I tried to fix it. The fix is attached. Reproducible: Always Steps to Reproduce: Following the steps to setup a web app to use JASPI for container-managed security, then access the protected resourcs in the web app, the problem could be reproduced. 1. Creating a JASPI configuration XML file for your auth module: <?xml version="1.0" encoding="UTF-8"?> <jaspi xmlns="http://geronimo.apache.org/xml/ns/geronimo-jaspi"> <configProvider> <messageLayer>HTTP</messageLayer> <appContext>/ui</appContext> <description>description</description> <serverAuthConfig> <authenticationContextID>authenticationContextID2</authenticationContextID> <protected>true</protected> <serverAuthContext> <serverAuthModule> <className>org.eclipse.jetty.security.jaspi.modules.FormAuthModule</className> <options> org.eclipse.jetty.security.jaspi.modules.LoginPage=/secure/jaaslogin org.eclipse.jetty.security.jaspi.modules.ErrorPage=/secure/jaaserror </options> </serverAuthModule> </serverAuthContext> </serverAuthConfig> <persistent>true</persistent> </configProvider> </jaspi> The above using the Jetty built-in FormAuthModule, if you want to use the built-in Basic or Digest auth module, the <serverAuthModule> part should be: <serverAuthModule> <className>org.eclipse.jetty.security.jaspi.modules.DigestAuthModule</className> <options> org.eclipse.jetty.security.jaspi.modules.RealmName=JAASRealm </options> </serverAuthModule> Or <serverAuthModule> <className>org.eclipse.jetty.security.jaspi.modules.BasicAuthModule</className> <options> org.eclipse.jetty.security.jaspi.modules.RealmName=JAASRealm </options> </serverAuthModule> Here I use the implementation of JASPI of geronimo-jaspi 2.0-SNAPSHOT from geronimo-jaspi (https://github.com/apache/geronimo-jaspi). you could use geronimo-jaspi 1.1.1 release, but you might need to implements javax.security.auth.message.config.AuthConfigProvider (and not javax.security.auth.message.module.ServerAuthModule) and configure it in the above XML file. 2. Configuring your AppContext to use JaspiAuthenticatorFactory. I configured it in jetty-web.xml file: <Configure class="org.eclipse.jetty.webapp.WebAppContext"> <Set name="securityHandler"> <New class="org.eclipse.jetty.security.ConstraintSecurityHandler"> <Set name="loginService"> <New class="org.eclipse.jetty.plus.jaas.JAASLoginService"> <Set name="name">JAASRealm</Set> <Set name="loginModuleName">jaas</Set> </New> </Set> <Set name="authenticatorFactory"> <New class="org.eclipse.jetty.security.jaspi.JaspiAuthenticatorFactory" /> </Set> </New> </Set> </Configure> 3. When launching Jetty, using -Dorg.apache.geronimo.jaspic.configurationFile to tell geronimo-jaspi where to find the JASPI configuration file. The following is the jetty-maven-plugin configuration (my JASPI configuration file is form-test-jaspi-2.xml): <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>${jetty.version}</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <webAppConfig> <contextPath>/ui</contextPath> <parentLoaderPriority>true</parentLoaderPriority> </webAppConfig> <systemProperties> <systemProperty> <name>java.security.auth.login.config</name> <value>./conf/jetty/jaas.conf</value> </systemProperty> <systemProperty> <name>org.apache.geronimo.jaspic.configurationFile</name> <value>./conf/jaspi/form-test-jaspi-2.xml</value> </systemProperty> </configuration> <dependencies> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-jaspi</artifactId> <version>${jetty.version}</version> </dependency> <dependency> <groupId>org.apache.geronimo.components</groupId> <artifactId>geronimo-jaspi</artifactId> <version>2.0-SNAPSHOT</version> </dependency> </dependencies> </plugin> In my test, I use my own JAAS login module, which configured in jaas.conf. you could use Jetty built-in login module as described in http://wiki.eclipse.org/Jetty/Feature/JAAS.
Created attachment 204240 [details] The attached is the fix for Jetty 8.0.1.v20110908
More info via email from Guofeng: One thing I want to mention it here because I wonder if it will affect the stability of Jetty when it is deployed on the product environment. You please pay attention on it. In the process of debugging my fix, sometime when an exception (like NullPointerException or ServerAuthException) thrown, the Jetty print on Dos Console the following: 11:49:27.583 [qtp21447570-16] DEBUG o.e.jetty.server.AsyncHttpConnection - async request 11:49:27.583 [qtp21447570-20] DEBUG o.e.jetty.server.AsyncHttpConnection - async request 11:49:27.583 [qtp21447570-18] DEBUG o.e.jetty.server.AsyncHttpConnection - async request 11:49:27.583 [qtp21447570-15] DEBUG o.e.jetty.server.AsyncHttpConnection - async request 11:49:27.583 [qtp21447570-17] DEBUG o.e.jetty.server.AsyncHttpConnection - async request 11:49:27.583 [qtp21447570-16] DEBUG o.e.jetty.server.AsyncHttpConnection - async request 11:49:27.583 [qtp21447570-19] DEBUG o.e.jetty.server.AsyncHttpConnection - async request 11:49:27.583 [qtp21447570-20] DEBUG o.e.jetty.server.AsyncHttpConnection - async request It flood the console and causes the CPU 100% usage. Jetty is very slow to response the request. When the fix works well. This does not occur again. To reproduce it, try to change secureResponse() in JaspiAuthenticator like the following to throw an exception (this occurs before my fix in that info in req is null): public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException { JaspiMessageInfo info = (JaspiMessageInfo)req.getAttribute("org.eclipse.jetty.security.jaspi.info"); //if (info==null) throw new NullPointerException("MeesageInfo from request missing: " + req); //return secureResponse(info,validatedUser); } I do not know whether it is a bug or because it is in the debug phrase, so I mention it here.
Hi Guofeng, I seem to have a problem with the geronimo-jaspi jars. I checked out git://github.com/apache/geronimo-jaspi.git and built the geronimo-jaspi module, however the geronimo-jaspi jar that was produced does not contain any of the org/apache/geronimo/components/jaspi/impl/ classes, so when I run jetty I get: 2011-09-29 16:38:53.315:INFO:oejs.Server:jetty-7.5.2-SNAPSHOT 2011-09-29 16:38:53.603:INFO:oejpw.PlusConfiguration:No Transaction manager found - if your webapp requires one, please configure one. 2011-09-29 16:38:53.771:WARN:oejuc.AbstractLifeCycle:FAILED org.eclipse.jetty.security.ConstraintSecurityHandler@50f8ae79#FAILED: java.lang.NoClassDefFoundError: org/apache/geronimo/components/jaspi/impl/ConfigProviderImpl java.lang.NoClassDefFoundError: org/apache/geronimo/components/jaspi/impl/ConfigProviderImpl at org.apache.geronimo.components.jaspi.AuthConfigFactoryImpl.initialize(AuthConfigFactoryImpl.java:279) at org.apache.geronimo.components.jaspi.AuthConfigFactoryImpl.loadConfig(AuthConfigFactoryImpl.java:271) at org.apache.geronimo.components.jaspi.AuthConfigFactoryImpl.<init>(AuthConfigFactoryImpl.java:75) at org.apache.geronimo.components.jaspi.AuthConfigFactoryImpl.<init>(AuthConfigFactoryImpl.java:79) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at java.lang.Class.newInstance0(Class.java:355) at java.lang.Class.newInstance(Class.java:308) at javax.security.auth.message.config.AuthConfigFactory$3.run(AuthConfigFactory.java:66) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.message.config.AuthConfigFactory.getFactory(AuthConfigFactory.java:62) at org.eclipse.jetty.security.jaspi.JaspiAuthenticatorFactory.getAuthenticator(JaspiAuthenticatorFactory.java:91) at org.eclipse.jetty.security.SecurityHandler.doStart(SecurityHandler.java:323) at org.eclipse.jetty.security.ConstraintSecurityHandler.doStart(ConstraintSecurityHandler.java:228) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:89) at org.eclipse.jetty.server.handler.ScopedHandler.doStart(ScopedHandler.java:97) at org.eclipse.jetty.server.session.SessionHandler.doStart(SessionHandler.java:116) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:89) at org.eclipse.jetty.server.handler.ScopedHandler.doStart(ScopedHandler.java:97) at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:632) at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:233) at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1213) at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:589) at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:454) at org.mortbay.jetty.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:248) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224) at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:167) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:89) at org.eclipse.jetty.server.Server.doStart(Server.java:261) at org.mortbay.jetty.plugin.JettyServer.doStart(JettyServer.java:65) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:481) at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:334) at org.mortbay.jetty.plugin.JettyRunMojo.execute(JettyRunMojo.java:513) at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59) at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183) at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161) at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319) at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156) at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537) at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196) at org.apache.maven.cli.MavenCli.main(MavenCli.java:141) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290) at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230) at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409) at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352) Can you attach to this issue a version of the geronimo-jaspi jars that work? Or tell me how to generate jaspi jars that will work? thanks Jan
add the following line to maven-bundle-plugin in geronimo-jaspi/pom.xml <Private-Package>org.apache.geronimo.components.jaspi.impl.*</Private-Package>, which will like: <instructions> .... <Private-Package>org.apache.geronimo.osgi.locator</Private-Package> <Private-Package>org.apache.geronimo.components.jaspi.impl.*</Private-Package> <Bundle-Activator>org.apache.geronimo.osgi.locator.Activator</Bundle-Activator> </instructions> When lauching jetty, if you met NoClassDefFoundError for ProviderLocator class, you need to add the following dependency for jetty-maven-plugin: <dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-osgi-locator</artifactId> <version>1.0</version> </dependency>
Thanks, I seem to have overcome those problems now. Can you confirm if the error you saw before your fixes was this: java.lang.NullPointerException: MeesageInfo from request missing: [GET /foo/]@116134643 org.eclipse.jetty.server.Request@6ec12f3 at org.eclipse.jetty.security.jaspi.JaspiAuthenticator.secureResponse(JaspiAuthenticator.java:94) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:500) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:940) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:409) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:186) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:874) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250) at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110) at org.eclipse.jetty.server.Server.handle(Server.java:349) at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:441) at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:914) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:565) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:217) at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:52) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:555) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:43) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:598) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:533) at java.lang.Thread.run(Thread.java:662) ? thanks Jan (In reply to comment #4) > add the following line to maven-bundle-plugin in geronimo-jaspi/pom.xml > > <Private-Package>org.apache.geronimo.components.jaspi.impl.*</Private-Package>, > which will like: > > <instructions> > .... > > <Private-Package>org.apache.geronimo.osgi.locator</Private-Package> > > <Private-Package>org.apache.geronimo.components.jaspi.impl.*</Private-Package> > > <Bundle-Activator>org.apache.geronimo.osgi.locator.Activator</Bundle-Activator> > </instructions> > > > When lauching jetty, if you met NoClassDefFoundError for ProviderLocator class, > you need to add the following dependency for jetty-maven-plugin: > <dependency> > <groupId>org.apache.geronimo.specs</groupId> > <artifactId>geronimo-osgi-locator</artifactId> > <version>1.0</version> > </dependency>
Yes. (In reply to comment #5) > Thanks, I seem to have overcome those problems now. > Can you confirm if the error you saw before your fixes was this: > java.lang.NullPointerException: MeesageInfo from request missing: [GET > /foo/]@116134643 org.eclipse.jetty.server.Request@6ec12f3 > at > org.eclipse.jetty.security.jaspi.JaspiAuthenticator.secureResponse(JaspiAuthenticator.java:94) > at > org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:500) > at > org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227) > at > org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:940) > at > org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:409) > at > org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:186) > at > org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:874) > at > org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) > at > org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250) > at > org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149) > at > org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110) > at org.eclipse.jetty.server.Server.handle(Server.java:349) > at > org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:441) > at > org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:914) > at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:565) > at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:217) > at > org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:52) > at > org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:555) > at > org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:43) > at > org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:598) > at > org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:533) > at java.lang.Thread.run(Thread.java:662) > ? > thanks > Jan > (In reply to comment #4) > > add the following line to maven-bundle-plugin in geronimo-jaspi/pom.xml > > > > <Private-Package>org.apache.geronimo.components.jaspi.impl.*</Private-Package>, > > which will like: > > > > <instructions> > > .... > > > > <Private-Package>org.apache.geronimo.osgi.locator</Private-Package> > > > > <Private-Package>org.apache.geronimo.components.jaspi.impl.*</Private-Package> > > > > <Bundle-Activator>org.apache.geronimo.osgi.locator.Activator</Bundle-Activator> > > </instructions> > > > > > > When lauching jetty, if you met NoClassDefFoundError for ProviderLocator class, > > you need to add the following dependency for jetty-maven-plugin: > > <dependency> > > <groupId>org.apache.geronimo.specs</groupId> > > <artifactId>geronimo-osgi-locator</artifactId> > > <version>1.0</version> > > </dependency>
Yes. but it is not the root of the issue. I do not make any changes to JaspiAuthenticator.secureResponse(). By fixing other part, it works well. (In reply to comment #6) > Yes. > (In reply to comment #5) > > Thanks, I seem to have overcome those problems now. > > Can you confirm if the error you saw before your fixes was this: > > java.lang.NullPointerException: MeesageInfo from request missing: [GET > > /foo/]@116134643 org.eclipse.jetty.server.Request@6ec12f3 > > at > > org.eclipse.jetty.security.jaspi.JaspiAuthenticator.secureResponse(JaspiAuthenticator.java:94) > > at > > org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:500) > > at > > org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227) > > at > > org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:940) > > at > > org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:409) > > at > > org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:186) > > at > > org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:874) > > at > > org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) > > at > > org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250) > > at > > org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149) > > at > > org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110) > > at org.eclipse.jetty.server.Server.handle(Server.java:349) > > at > > org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:441) > > at > > org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:914) > > at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:565) > > at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:217) > > at > > org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:52) > > at > > org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:555) > > at > > org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:43) > > at > > org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:598) > > at > > org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:533) > > at java.lang.Thread.run(Thread.java:662) > > ? > > thanks > > Jan > > (In reply to comment #4) > > > add the following line to maven-bundle-plugin in geronimo-jaspi/pom.xml > > > > > > <Private-Package>org.apache.geronimo.components.jaspi.impl.*</Private-Package>, > > > which will like: > > > > > > <instructions> > > > .... > > > > > > <Private-Package>org.apache.geronimo.osgi.locator</Private-Package> > > > > > > <Private-Package>org.apache.geronimo.components.jaspi.impl.*</Private-Package> > > > > > > <Bundle-Activator>org.apache.geronimo.osgi.locator.Activator</Bundle-Activator> > > > </instructions> > > > > > > > > > When lauching jetty, if you met NoClassDefFoundError for ProviderLocator class, > > > you need to add the following dependency for jetty-maven-plugin: > > > <dependency> > > > <groupId>org.apache.geronimo.specs</groupId> > > > <artifactId>geronimo-osgi-locator</artifactId> > > > <version>1.0</version> > > > </dependency>
Hi Guofeng, I think there is an error in the geronimo-jaspi implementation in the ServerAuthContextImpl class, line 73: if (result == AuthStatus.SEND_SUCCESS || result == AuthStatus.SEND_CONTINUE || result == AuthStatus.FAILURE) { return result; } throw new AuthException("Invalid AuthStatus " + result + " from server auth module validateRequest: " + serverAuthModule); According to the final release of the Jaspi Specification, the javadocs for ServerAuth interface, p. 88, the following are the only allowable results for the validateRequest(MessageInfo,Subject,Subject): • AuthStatus.SUCCESS when the application request message was successfully validated. The validated request message is available by calling getRequestMessage on messageInfo. • AuthStatus.SEND_SUCCESS to indicate that validation/processing of the request message successfully produced the secured application response message (in messageInfo). The secured response message is available by calling getResponseMessage on messageInfo. • AuthStatus.SEND_CONTINUE to indicate that message validation is incomplete, and that a preliminary response was returned as the response message in messageInfo. When this status value is returned to challenge an application request message, the challenged request must be saved by the authentication module such that it can be recovered when the module’s validateRequest message is called to process the request returned for the challenge. • AuthStatus.SEND_FAILURE to indicate that message validation failed and that an appropriate failure response message is available by calling getResponseMessage on messageInfo. The FormAuthModule is returning AuthStatus.SEND_FAILURE (eg to indicate that the user's password was not authenticated), but the ServerAuthContextImpl class is expecting AuthStatus.FAILURE instead. cheers Jan
Guofeng, I've made a branch called "bug-359329" which you can check out from the jetty git repo at http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git I've made a few modifications so that jaspi appears to now be working, at least with FORM authentication. I haven't tried it with BASIC auth yet. There's a lot of debug left in the code for now, as I'd like David Jencks to have a look at it, as I think there's a lot of scope for cleaning up and rationalising the jaspi impl - I think it got left behind as the jetty codebase changed around it. If you would like to checkout and build the branch and test it against your set up, that would be very helpful. thanks, Jan
(In reply to comment #9) I tested your branch using FormAuthModule, but it does not works well. Steps 1. browse "http://localhost:8080/ui/jasssecured/index", where jasssecured/* is container-protected resources. 2. the FORM login page configured in web.xml is displayed. (correct) The error is the saved juri is incorrect: Redirecting to login page /secure/jaaslogin and remembering juri=http://localhos t:8080/ui/ajax_request/liftAjax.js the remembering juri should be "localhost:8080/ui/jasssecured/index", not "http://localhost:8080/ui/ajax_request/liftAjax.js". 3. type correct user name and password, liftAjax.js is displayed, instead of index.html. I met this case in my fix, I did it as the following: //** Don't auth the Deferred authentication. Authentication authentication = ((org.eclipse.jetty.server.Request)request).getAuthentication() ; if (authentication instanceof Authentication.Deferred ) return AuthStatus.SEND_SUCCESS; before: session.setAttribute(__J_URI, buf.toString()); in FormAuthModule.validateRequest(JaspiMessageInfo messageInfo) In JaspiAuthenticator.validateRequest(ServletRequest request, ServletResponse response, boolean mandatory), I removed the following: if (_allowLazyAuthentication && !mandatory) return _deferred; and added in JaspiAuthenticator.validateRequest(JaspiMessageInfo messageInfo) the following: if (authStatus == AuthStatus.SUCCESS) { if ( !isMandatory( messageInfo ) ) return _deferred ; In my mail, I said I do not know if I did the above change to JaspiAuthenticator correctly. Does the change make FormAuthModule to deal with Authentication.Deferred in the above if statement?
Guofeng, What is referencing the ajax_request/liftAjax.js? Is it the form login page? Do you have static resources that are referenced by a protected url, but that are not themselves protected? Or are the static resources also behind a protected url? thanks Jan (In reply to comment #10) > (In reply to comment #9) > > I tested your branch using FormAuthModule, but it does not works well. > Steps > 1. browse "http://localhost:8080/ui/jasssecured/index", where jasssecured/* is > container-protected resources. > 2. the FORM login page configured in web.xml is displayed. (correct) > The error is the saved juri is incorrect: > Redirecting to login page /secure/jaaslogin and remembering > juri=http://localhos > t:8080/ui/ajax_request/liftAjax.js > > the remembering juri should be "localhost:8080/ui/jasssecured/index", not > "http://localhost:8080/ui/ajax_request/liftAjax.js". > > 3. type correct user name and password, liftAjax.js is displayed, instead of > index.html. > > I met this case in my fix, I did it as the following: > //** Don't auth the Deferred authentication. > Authentication authentication = > ((org.eclipse.jetty.server.Request)request).getAuthentication() ; > if (authentication instanceof Authentication.Deferred ) > return AuthStatus.SEND_SUCCESS; > > before: > session.setAttribute(__J_URI, buf.toString()); > in FormAuthModule.validateRequest(JaspiMessageInfo messageInfo) > > In JaspiAuthenticator.validateRequest(ServletRequest request, ServletResponse > response, boolean mandatory), I removed the following: > if (_allowLazyAuthentication && !mandatory) > return _deferred; > > and added in JaspiAuthenticator.validateRequest(JaspiMessageInfo messageInfo) > the following: > if (authStatus == AuthStatus.SUCCESS) > { > if ( !isMandatory( messageInfo ) ) > return _deferred ; > > In my mail, I said I do not know if I did the above change to > JaspiAuthenticator correctly. Does the change make FormAuthModule to deal with > Authentication.Deferred in the above if statement?
And also, I made some changes to the uri that was saved before doing the re-direct, so can you check that your branch is up-to-date? thanks Jan (In reply to comment #11) > Guofeng, > > What is referencing the ajax_request/liftAjax.js? Is it the form login page? > Do you have static resources that are referenced by a protected url, but that > are not themselves protected? Or are the static resources also behind a > protected url? > > thanks > Jan > > > > > > > > (In reply to comment #10) > > (In reply to comment #9) > > > > I tested your branch using FormAuthModule, but it does not works well. > > Steps > > 1. browse "http://localhost:8080/ui/jasssecured/index", where jasssecured/* is > > container-protected resources. > > 2. the FORM login page configured in web.xml is displayed. (correct) > > The error is the saved juri is incorrect: > > Redirecting to login page /secure/jaaslogin and remembering > > juri=http://localhos > > t:8080/ui/ajax_request/liftAjax.js > > > > the remembering juri should be "localhost:8080/ui/jasssecured/index", not > > "http://localhost:8080/ui/ajax_request/liftAjax.js". > > > > 3. type correct user name and password, liftAjax.js is displayed, instead of > > index.html. > > > > I met this case in my fix, I did it as the following: > > //** Don't auth the Deferred authentication. > > Authentication authentication = > > ((org.eclipse.jetty.server.Request)request).getAuthentication() ; > > if (authentication instanceof Authentication.Deferred ) > > return AuthStatus.SEND_SUCCESS; > > > > before: > > session.setAttribute(__J_URI, buf.toString()); > > in FormAuthModule.validateRequest(JaspiMessageInfo messageInfo) > > > > In JaspiAuthenticator.validateRequest(ServletRequest request, ServletResponse > > response, boolean mandatory), I removed the following: > > if (_allowLazyAuthentication && !mandatory) > > return _deferred; > > > > and added in JaspiAuthenticator.validateRequest(JaspiMessageInfo messageInfo) > > the following: > > if (authStatus == AuthStatus.SUCCESS) > > { > > if ( !isMandatory( messageInfo ) ) > > return _deferred ; > > > > In my mail, I said I do not know if I did the above change to > > JaspiAuthenticator correctly. Does the change make FormAuthModule to deal with > > Authentication.Deferred in the above if statement?
(In reply to comment #8) Yes. You are right. for my fix, I let FormAuthModule return SEND_CONTINUE. but this is just temporary for me.
(In reply to comment #12) liftAjax.js is refereneced in the form login page. it is not protected by Jetty. The form login page and all resources referenced in the form login page are not protected. I tested the last change in the branch. case 1 passed, but others failed. case 1: (1) let the browser point to the protected page: http://localhost:8080/ui/jasssecured/index (2) the login page displayed correctly, type the correct user name and password, the index page is displayed. this test case passed. case 2: (1) let the browser point to the protected page: http://localhost:8080/ui/jasssecured/index (2) the login page displayed correctly, type the wrong user name and/or password to force the login failure. (3) login error page displayed correctly. there is a link on the error page to go to the login page again. (4) on the login page, type correct user name and password, the console output indicate that the login module works well. but the browser still display the login page. type http://localhost:8080/ui/jasssecured/index directly in the address bar, the index page displayed correctly. in step 3, if i donot click the link on the error page to go to the form login page directly, but type http://localhost:8080/ui/jasssecured/index in the address bar, the form login page displayed correctly. Type correct user name and password, the bahavior is the same as (4). case 3: open the form login page directly: http://localhost:8080/ui/secure/jaaslogin. type correct user name and password. the browser still display the login page. then type http://localhost:8080/ui/jasssecured/index, the index page displayed directly.
Created attachment 204981 [details] Tar file of small test webapp maven project for jaspi testing Small test webapp for doing jaspi testing.
Guofeng, I have not been able to reproduce the problems you reported. Did you check that your browser caches had been emptied before doing the tests? I've also attached a small test webapp that I'm using. After unpacking it, do: mvn jetty:run Then hit the url http://localhost:8080/foo/auth.html. Click on the link that says "jaspi/index.html - Authenticated Any User" to hit a protected url that will force you to the login form. cheers Jan
Created attachment 204993 [details] the test web app for JASPI fix
Created attachment 205006 [details] my test web app This attachment can reproduce the failure described in comment 14.
(In reply to comment #18) > Created attachment 205006 [details] > my test web app > > This attachment can reproduce the failure described in comment 14. Using your test web app, I cannot reproduce the failure described in comment 14. but using my web app, it can be reproduced. I use the same browser: Google Chrome 16.0.899.0. The attached is a simplified version of my web app. but It can be used to reproduce the errors. I think the issue might relate to the session setting after the successful authentication. In org.planner.ui.bootstrap.Boot.scala, I have the following code: LiftRules.earlyInStateful.append( ignoredReq => { Authentication.tryToStoreCurrentUserAndRolesInSession() } ) /* // Check Login - if not login, directory to /secure/login LiftRules.dispatch.prepend(NamedPF("Login Validation") { case Req( page, "", _) if !MUser.loggedIn_? && page.head != "secure" && page.head != "static" => { _log.debug( "MUser.loggedIn_?:"+MUser.loggedIn_? + " page:" + page); () => Full(RedirectResponse("/secure/jaaslogin")) } }) */ I comment the last part so that the form login page is not affected by this part. If I comment out: LiftRules.earlyInStateful.append( ignoredReq => { Authentication.tryToStoreCurrentUserAndRolesInSession() } ) Your fix works well using the test cases in comment 14. but if I enable it (i.e, uncomment it), the errors described in comment 14 reproduced. The above code only store the user object in the session. In my attachment, there are myfixlog and yourfixlog. you can compare the difference. Main part as the following: Yours: 16:57:09.598 [qtp6435687-18 - /ui/secure/j_security_check] DEBUG org.eclipse.jetty.server.Server - REQUEST /ui/secure/j_security_check on org.eclipse.jetty.server.nio.SelectChannelConnector$SelectChannelHttpConnection@dc5434@127.0.0.1:8080<->127.0.0.1:1233 ....... 16:57:09.645 [qtp6435687-18 - /ui/secure/j_security_check] DEBUG org.eclipse.jetty.server.Server - RESPONSE /ui/secure/j_security_check 302 ... ==>16:57:09.645 [qtp6435687-19 - /ui/secure/jaaslogin] DEBUG org.eclipse.jetty.server.Server - REQUEST /ui/secure/jaaslogin on org.eclipse.jetty.server.nio.SelectChannelConnector$SelectChannelHttpConnection@dc5434@127.0.0.1:8080<->127.0.0.1:1233 My: 17:00:20.695 [qtp6847200-18 - /ui/secure/j_security_check] DEBUG org.eclipse.jetty.server.Server - REQUEST /ui/secure/j_security_check on org.eclipse.jetty.server.nio.SelectChannelConnector$SelectChannelHttpConnection@6e18b0@127.0.0.1:8080<->127.0.0.1:1261 ... 17:00:20.758 [qtp6847200-18 - /ui/secure/j_security_check] DEBUG org.eclipse.jetty.server.Server - RESPONSE /ui/secure/j_security_check 302 ==>17:00:20.758 [qtp6847200-20 - /ui/jasssecured/index] DEBUG org.eclipse.jetty.server.Server - REQUEST /ui/jasssecured/index on org.eclipse.jetty.server.nio.SelectChannelConnector$SelectChannelHttpConnection@6e18b0@127.0.0.1:8080<->127.0.0.1:1261 Another: I find that your fix will invoke the login module when the user has been authenticated and the protected resource is re-accessed. I think it should not invoke the login module if the user has been authenticated (the authentication might take time and deal with it in the login module is not an easy task). There are two subdirectories in my attachmeht. first you could build security module (containing the login module). then using mvn jetty:run in the ui module to run jetty. NOTE THAT the user name and password is hard coded as "admin" and "password" in the login module. you can access the protected resource using: localhost:8080/ui/jasssecured/index it should display the form login page. input "admin/password" to log in or test the failure cases.
(In reply to comment #19) you please first change the jetty.version property to 7.5.2-SNAPSHOT of pom.xml in the root directory. In the attachment it is set as the following: <properties> .... <jetty.version>8.0.3.v20111011</jetty.version> <!--jetty.version>7.5.2-SNAPSHOT</jetty.version--> ... </properties>
Hi Guofeng, > Another: I find that your fix will invoke the login module when the user has > been authenticated and the protected resource is re-accessed. I think it should > not invoke the login module if the user has been authenticated (the > authentication might take time and deal with it in the login module is not an > easy task). The FormAuthModule validateRequest will always be called, but unless J_SECURITY_CHECK is on the request url (ie its the form login module POST), then the JAAS login module should not be called. I'm still trying to work out why calling request.getRemoteUser() should cause the problem shown by your test webapp. Will post later when I have more info. cheers Jan
(In reply to comment #21) > > The FormAuthModule validateRequest will always be called, but unless > J_SECURITY_CHECK is on the request url (ie its the form login module POST), > then the JAAS login module should not be called. > FormAuthModule.validateRequest() will invoke the login module using the following code: if (form_cred != null) { boolean success = tryLogin(messageInfo, clientSubject, response, session, form_cred._jUserName, new Password(new String(form_cred._jPassword))); if (success) { return AuthStatus.SUCCESS; } } I think the session has been authenticated when form_cred is not null, so I change it to: if (form_cred != null) { clientSubject.getPrivateCredentials().addAll( form_cred._subject.getPrivateCredentials( UserIdentity.class) ) ; return AuthStatus.SUCCESS; } For this, I add Subject field in FormCredential class: private static class FormCredential implements Serializable, HttpSessionBindingListener { .... transient Subject _subject ; private FormCredential(String _jUserName, char[] _jPassword, Principal _userPrincipal, Subject subject) { ....... this._subject = subject ; } and in tryLogin() method, if the user is authenticated successfully: if (!loginCallbacks.isEmpty()) { LoginCallbackImpl loginCallback = loginCallbacks.iterator().next(); FormCredential form_cred = new FormCredential(username, pwdChars, loginCallback.getUserPrincipal(), loginCallback.getSubject() ); session.setAttribute(__J_AUTHENTICATED, form_cred); } In this way, if the session has been authenticated, the login module won't be invoked again.
Hi Guofeng, I fixed the FormAuthModule so that your test webapp worked. Changes checked into the branch. It was a silly error with checking if the inbound request matched the login page. So you should be good to update your branch and try again (Note that the jetty version has changed to 7.5.4-SNAPSHOT as I've merged HEAD into the branch). As for trying to avoid invoking the LoginModule for a request for protected resource AFTER authentication has already taken place, that is a bit more problematic. I see with your workaround you are trying to use the information in the Subject to achieve it, however I don't think we're 100% there with that solution. I think we somehow need to invoke the LoginService.validate(UserIdentity) method, which is what the other non-jaspi jetty authentication code does (eg see FormAuthenticator line 240). The difficulty is that the FormAuthModule does not know about the LoginService, so that is going to be difficult to arrange. I will think about this one over the weekend. cheers Jan (In reply to comment #22) > (In reply to comment #21) > > > > The FormAuthModule validateRequest will always be called, but unless > > J_SECURITY_CHECK is on the request url (ie its the form login module POST), > > then the JAAS login module should not be called. > > > > FormAuthModule.validateRequest() will invoke the login module using the > following code: > if (form_cred != null) > { > boolean success = tryLogin(messageInfo, clientSubject, > response, session, form_cred._jUserName, new Password(new > String(form_cred._jPassword))); > if (success) { return AuthStatus.SUCCESS; } > } > I think the session has been authenticated when form_cred is not null, so I > change it to: > if (form_cred != null) > { > clientSubject.getPrivateCredentials().addAll( > form_cred._subject.getPrivateCredentials( UserIdentity.class) ) ; > return AuthStatus.SUCCESS; > } > > For this, I add Subject field in FormCredential class: > private static class FormCredential implements Serializable, > HttpSessionBindingListener > { > .... > transient Subject _subject ; > > private FormCredential(String _jUserName, char[] _jPassword, Principal > _userPrincipal, Subject subject) > { > ....... > this._subject = subject ; > } > and in tryLogin() method, if the user is authenticated successfully: > if (!loginCallbacks.isEmpty()) > { > LoginCallbackImpl loginCallback = > loginCallbacks.iterator().next(); > FormCredential form_cred = new FormCredential(username, > pwdChars, loginCallback.getUserPrincipal(), loginCallback.getSubject() ); > > session.setAttribute(__J_AUTHENTICATED, form_cred); > } > In this way, if the session has been authenticated, the login module won't be > invoked again.
(In reply to comment #23) Hi Jan, Hi, Jan, Could you deploy 7.5.4_SNAPSHOT to https://oss.sonatype.org/content/groups/jetty/, especially jetty-maven-plugin:7.5.4_SNAPSHOT. I do not know how to launch 7.5.4_SNAPSHOT jetty server using the plugin. > > I think we somehow need to invoke the LoginService.validate(UserIdentity) > method, which is what the other non-jaspi jetty authentication code does (eg > see FormAuthenticator line 240). The difficulty is that the FormAuthModule does > not know about the LoginService, so that is going to be difficult to arrange. I do not have the bird-view of Jetty's identity/authentication service. By browsing ServletCallbackHandler class in jetty-jaspi module, I have made that workarround, so I do not know if I did it well. You please make your decision. But I think avoid invoking the login module is a useful requirement. I forget mentioning the following in my comment 22. I also made changes to ServletCallbackHandler.handle(), I added: else if (callback instanceof CredentialValidationCallback) { ... if (user!=null) { ..... credentialValidationCallback.getSubject().getPrivateCredentials().add( loginCallback ) ; } } loginService is called here. loginServer should reference to JAASLoginServer, the login method of JAASLoginService has no side-effect, but return a identity service instance which wrapping the subject. So I think it might be not problematic not to call loginService.login() when the session has been authenticated. Thanks!
(In reply to comment #24) > (In reply to comment #23) > > Hi Jan, > Could you deploy 7.5.4_SNAPSHOT to > https://oss.sonatype.org/content/groups/jetty/, especially > jetty-maven-plugin:7.5.4_SNAPSHOT. I do not know how to launch 7.5.4_SNAPSHOT > jetty server using the plugin. > I tested 7.5.4-SNAPSHOT using my test app. The following cases passed: (1) accss http://localhost:8080/ui/jasssecured/index, the login page displayed, type correct user name and password, the index.html page is displayed (passed) (2) accss http://localhost:8080/ui/secure/jaaslogin, that is, directly open the form login page, type correctly user name and password, the root index page (/) displayed. (passed) But if I input incorrect username or password for the above two cases, the result is not expected: (1) accss http://localhost:8080/ui/jasssecured/index, the login page displayed, type incorrect user name or password, the form error page is displayed. On this page, there is a link to the form login page, click it to go to the login page again, then type correct user name and password, the displayed page is still the login page. the expected result should be the index page is displayed. (not passed) (2) accss http://localhost:8080/ui/secure/jaaslogin, that is, directly open the form login page, type incorrect user name and password, the form error page is displayed. Click the link on the page to go to the login page again. Type correct user name and password, the displayed page is still the login page. the expected result should be the root index page (that is, /) is displayed. (not passed)
(In reply to comment #25) Hi Guofeng, There's a couple of things that are stopping cases 2 and 3 working as expected. Firstly, the jaspi module has been configured with the login and error pages as /secure/jaaslogin and /secure/jaaserror, but the link on the jaaserror page links to /secure/jaaslogin.html. The FormAuthModule has no way of knowing that /secure/jaaslogin and /secure/jaaslogin.html are the same thing because of the framework you're using. Changing the link to /secure/jaaslogin removes this problem. After fixing the link, and after incorrectly entering the login name/pwd,then following the link, and then correctly entering the login name/pwd, the contents of the /ui/ajax_request/liftAjax.js are displayed. The reason for this is: 1. the incoming request for the /ui/ajax_request/liftAjax.js - which is not behind a protected url - is handled by the SecurityHandler/jaspi as a Deferred authentication. 2. the same incoming request then passes through to the servlet, which passes it to the Authentication.tryToStoreCurrentUserAndRolesInSession method, which triggers the Deferred authentication to authenticate the user, which redirects to the login page (because no login has succeeded yet), and remembers the page that was being requested that triggered the authentication. So, because of the Authentication.tryToStoreCurrentUserAndRolesInSession JaspiAuthenticator.validateRequest() will be called for every request, even on urls that are not protected. For urls that are protected, JaspiAuthenticator.validateRequest() will sometimes be called twice: once by the SecurityHandler looking after the protected url, and then once by the Authentication.tryToStoreCurrentUserAndRolesInSession. cheers Jan
Guofeng, OK, I've added support for calling Request.getRemoteUser() on a DeferredAuthentication. When this happens, the FormAuthModule cannot really process the authentication, because it cannot send a challenge to direct the user to the form and thus capture the username/password. So in this edge case, the FormAuthModule really has to return AuthStatus.SUCCESS (same as it does if the auth isn't mandatory). So I think all of your test cases are now working - but please do let me know if not. thanks Jan
(In reply to comment #27) Hi jan, My tests passed. Thanks!
Released in 7.6.0.RC3.
(In reply to comment #29) > Released in 7.6.0.RC3. When will it be merged to 8.x? we know that it not works in 8.x either.
Hi Guofeng, it was merged into jetty-8 in time for a RC3 release but we don't seem to have done that release. In any case, it is all ready to go next time we do a release of jetty-8. cheers Jan
Jan, I tried 8.1.0.RC4. I found that you have merged what I mentioned in Comment 22 and Comment 24 about not invoking login module again when the user has been authenticated. I wonder if you forget the following change in FormAuthModule.validateRequest: //TODO: we would like the form auth module to be able to invoke the loginservice.validate() method to check the previously authed user // //boolean success = tryLogin(messageInfo, clientSubject, response, session, form_cred._jUserName, new Password(new String(form_cred._jPassword))); //if (success) { return AuthStatus.SUCCESS; } //** Change to: clientSubject.getPrivateCredentials().addAll( form_cred._subject.getPrivateCredentials( UserIdentity.class) ) ; return AuthStatus.SUCCESS; If the above change is not merged, the login module will be always called even if the user has logged in successfully. Hope I understand the RC4 code correctly. Guofeng
Hi Guofeng, I can't quite remember exactly, but I thought we avoided calling the LoginModule again because when we go into FormAuthModule.validateRequest, it is not mandatory? Can you go back to using the bug-359329 branch, as it has debug output in it, and send me the log that shows that we call the LoginModule even if the user has already been authenticated??? thanks, Jan (In reply to comment #32) > Jan, > > I tried 8.1.0.RC4. I found that you have merged what I mentioned in Comment 22 > and Comment 24 about not invoking login module again when the user has been > authenticated. I wonder if you forget the following change in > FormAuthModule.validateRequest: > //TODO: we would like the form auth module to be able to invoke > the loginservice.validate() method to check the previously authed user > // > //boolean success = tryLogin(messageInfo, clientSubject, > response, session, form_cred._jUserName, new Password(new > String(form_cred._jPassword))); > //if (success) { return AuthStatus.SUCCESS; } > //** Change to: > clientSubject.getPrivateCredentials().addAll( > form_cred._subject.getPrivateCredentials( UserIdentity.class) ) ; > return AuthStatus.SUCCESS; > > If the above change is not merged, the login module will be always called even > if the user has logged in successfully. > > Hope I understand the RC4 code correctly. > > Guofeng
(In reply to comment #33) > Hi Guofeng, > > I can't quite remember exactly, but I thought we avoided calling the > LoginModule again because when we go into FormAuthModule.validateRequest, it is > not mandatory? > > Can you go back to using the bug-359329 branch, as it has debug output in it, > and send me the log that shows that we call the LoginModule even if the user > has already been authenticated??? > > thanks, > Jan This test is done against my attached test web app. jasssecured/* is protected by web security in web.xml. (1) when I typed http://localhost:8080/ui/jasssecured/index. the login page display, and I did the log in: ..... ISLOGINORERRORPAGE? /jasssecured/index error: /secure/jaaserror login:/secure/jaaslogin Form cred: form.username=admin form.pwd=password user name: admin <----------My Login Module's output LoginCallbackImpls.isEmpty=false (2)then I typed http://localhost:8080/ui/jasssecured/first. ISLOGINORERRORPAGE? /jasssecured/first error: /secure/jaaserror login:/secure/jaaslogin Form cred: form.username=admin form.pwd=password user name: admin <----------My Login Module's output The following is the output. I removed the stacktrace. ISLOGINORERRORPAGE? / error: /secure/jaaserror login:/secure/jaaslogin FormAuthModule.validateRequest(info,subject,serviceSubject) for uri=/ui/ mandato ry=true isLoginOrError=false ISLOGINORERRORPAGE? / error: /secure/jaaserror login:/secure/jaaslogin JaspiAuthenticator.validateRequest returning UNAUTHENTICATED 16:47:09.114 [qtp5177132-15] INFO net.liftweb.util.TimeHelpers - Service reques t (GET) /ui/ returned 302, took 500 Milliseconds Securityhandler calling secureResponse, for Authentication.User JaspiAuthenticator.secureResponse uri=/ui/ JaspiAuthenticator.validateRequest, uri=/ui/secure/jaaslogin lazy=true mandatory =false ............... jaspAuthenticator.validateRequest(info) ISLOGINORERRORPAGE? /secure/jaaslogin error: /secure/jaaserror login:/secure/jaa slogin FormAuthModule.validateRequest(info,subject,serviceSubject) for uri=/ui/secure/j aaslogin mandatory=false isLoginOrError=true JaspiAuthenticator.validateRequest returning org.eclipse.jetty.security.authenti cation.DeferredAuthentication@135236e uri=/ui/secure/jaaslogin Auth is deferred JaspiAuthenticator.validateRequest, uri=/ui/secure/jaaslogin lazy=true mandatory =true .............. jaspAuthenticator.validateRequest(info) ISLOGINORERRORPAGE? /secure/jaaslogin error: /secure/jaaserror login:/secure/jaa slogin FormAuthModule.validateRequest(info,subject,serviceSubject) for uri=/ui/secure/j aaslogin mandatory=true isLoginOrError=true ISLOGINORERRORPAGE? /secure/jaaslogin error: /secure/jaaserror login:/secure/jaa slogin JaspiAuthenticator.validateRequest returning UNAUTHENTICATED 16:47:09.567 [qtp5177132-15] INFO net.liftweb.util.TimeHelpers - Service reques t (GET) /ui/secure/jaaslogin returned 200, took 438 Milliseconds Securityhandler calling secureResponse, for Authentication.User JaspiAuthenticator.secureResponse uri=/ui/secure/jaaslogin JaspiAuthenticator.validateRequest, uri=/ui/jasssecured/index lazy=true mandator y=true ............. jaspAuthenticator.validateRequest(info) ISLOGINORERRORPAGE? /jasssecured/index error: /secure/jaaserror login:/secure/ja aslogin FormAuthModule.validateRequest(info,subject,serviceSubject) for uri=/ui/jasssecu red/index mandatory=true isLoginOrError=false ISLOGINORERRORPAGE? /jasssecured/index error: /secure/jaaserror login:/secure/ja aslogin Redirecting to login page /secure/jaaslogin and remembering juri=http://localhos t:8080/ui/jasssecured/index JaspiAuthenticator.validateRequest returning CHALLENGE JaspiAuthenticator.validateRequest, uri=/ui/secure/j_security_check lazy=true ma ndatory=false .................. jaspAuthenticator.validateRequest(info) ISLOGINORERRORPAGE? /secure/j_security_check error: /secure/jaaserror login:/sec ure/jaaslogin FormAuthModule.validateRequest(info,subject,serviceSubject) for uri=/ui/secure/j _security_check mandatory=true isLoginOrError=false ISLOGINORERRORPAGE? /secure/j_security_check error: /secure/jaaserror login:/sec ure/jaaslogin Try login username=admin password=password user name: admin LoginCallbackImpls.isEmpty=false FormAuthModule, LoginCallbackImpl.isEmpty=false FormAuthModule succesful login, sending redirect to http://localhost:8080/ui/jas ssecured/index JaspiAuthenticator.validateRequest returning CHALLENGE JaspiAuthenticator.validateRequest, uri=/ui/jasssecured/index lazy=true mandator y=true ............... jaspAuthenticator.validateRequest(info) ISLOGINORERRORPAGE? /jasssecured/index error: /secure/jaaserror login:/secure/ja aslogin FormAuthModule.validateRequest(info,subject,serviceSubject) for uri=/ui/jasssecu red/index mandatory=true isLoginOrError=false ISLOGINORERRORPAGE? /jasssecured/index error: /secure/jaaserror login:/secure/jaaslogin Form cred: form.username=admin form.pwd=password user name: admin LoginCallbackImpls.isEmpty=false FormAuthModule, LoginCallbackImpl.isEmpty=false JaspiAuthenticator.validateRequest returning {User,JASPI,DefaultUserIdentity('ad min')} 16:47:27.504 [qtp5177132-20] INFO net.liftweb.util.TimeHelpers - Service reques t (GET) /ui/jasssecured/index returned 200, took 250 Milliseconds JaspiAuthenticator.secureResponse uri=/ui/jasssecured/index JaspiAuthenticator.validateRequest, uri=/ui/ajax_request/liftAjax.js lazy=true m andatory=false .............. jaspAuthenticator.validateRequest(info) ISLOGINORERRORPAGE? /ajax_request/liftAjax.js error: /secure/jaaserror login:/se cure/jaaslogin FormAuthModule.validateRequest(info,subject,serviceSubject) for uri=/ui/ajax_req uest/liftAjax.js mandatory=false isLoginOrError=false JaspiAuthenticator.validateRequest returning org.eclipse.jetty.security.authenti cation.DeferredAuthentication@135236e uri=/ui/ajax_request/liftAjax.js Auth is deferred JaspiAuthenticator.validateRequest, uri=/ui/ajax_request/liftAjax.js lazy=true m andatory=true ............... jaspAuthenticator.validateRequest(info) ISLOGINORERRORPAGE? /ajax_request/liftAjax.js error: /secure/jaaserror login:/se cure/jaaslogin FormAuthModule.validateRequest(info,subject,serviceSubject) for uri=/ui/ajax_req uest/liftAjax.js mandatory=true isLoginOrError=false ISLOGINORERRORPAGE? /ajax_request/liftAjax.js error: /secure/jaaserror login:/se cure/jaaslogin Form cred: form.username=admin form.pwd=password user name: admin LoginCallbackImpls.isEmpty=false FormAuthModule, LoginCallbackImpl.isEmpty=false JaspiAuthenticator.validateRequest returning {User,JASPI,DefaultUserIdentity('ad min')} 16:47:27.692 [qtp5177132-16] INFO net.liftweb.util.TimeHelpers - Service reques t (GET) /ui/ajax_request/liftAjax.js returned 200, took 157 Milliseconds Securityhandler calling secureResponse, for Authentication.User JaspiAuthenticator.secureResponse uri=/ui/ajax_request/liftAjax.js JaspiAuthenticator.validateRequest, uri=/ui/jasssecured/first lazy=true mandator y=true ..................... jaspAuthenticator.validateRequest(info) ISLOGINORERRORPAGE? /jasssecured/first error: /secure/jaaserror login:/secure/ja aslogin FormAuthModule.validateRequest(info,subject,serviceSubject) for uri=/ui/jasssecu red/first mandatory=true isLoginOrError=false ISLOGINORERRORPAGE? /jasssecured/first error: /secure/jaaserror login:/secure/jaaslogin Form cred: form.username=admin form.pwd=password user name: admin LoginCallbackImpls.isEmpty=false FormAuthModule, LoginCallbackImpl.isEmpty=false JaspiAuthenticator.validateRequest returning {User,JASPI,DefaultUserIdentity('ad min')} 16:47:33.020 [qtp5177132-18] INFO net.liftweb.util.TimeHelpers - Service reques t (GET) /ui/jasssecured/first returned 200, took 47 Milliseconds JaspiAuthenticator.secureResponse uri=/ui/jasssecured/first JaspiAuthenticator.validateRequest, uri=/ui/ajax_request/liftAjax.js lazy=true m andatory=false ...................... jaspAuthenticator.validateRequest(info) ISLOGINORERRORPAGE? /ajax_request/liftAjax.js error: /secure/jaaserror login:/se cure/jaaslogin FormAuthModule.validateRequest(info,subject,serviceSubject) for uri=/ui/ajax_req uest/liftAjax.js mandatory=false isLoginOrError=false JaspiAuthenticator.validateRequest returning {User,JASPI,DefaultUserIdentity('ad min')} 16:47:33.098 [qtp5177132-20] INFO net.liftweb.util.TimeHelpers - Service reques t (GET) /ui/ajax_request/liftAjax.js returned 200, took 0 Milliseconds JaspiAuthenticator.secureResponse uri=/ui/ajax_request/liftAjax.js
Hi Guofeng, I'd really rather find some way that the FormAuthModule could invoke the LoginService.validate method, but I just haven't been able to think of one! So failing that, I implemented your suggestion of copying the private credentials from the subject stored in the form_cred. I've committed that change to the branch - can you retest on your system? It seems to work for me, and doesn't seem to have broken anything else. thanks Jan
Reopening for the enhancement to avoid reinvoking LoginModule.login when already authenticated.
(In reply to comment #36) > Reopening for the enhancement to avoid reinvoking LoginModule.login when > already authenticated. It works OK now. Thanks!
Fixed for RC5.