Waffle Integration in spring security based JAMWiki project

1,583 views
Skip to first unread message

_theStudent_

unread,
Aug 30, 2012, 8:02:49 AM8/30/12
to waffle...@googlegroups.com
Hi,

I´m working on customizing a JAMWiki to support SSO with waffle auth. My problem is, that adding just the needed code lines from the "Single Sign-On: Spring-Security Negotiate Filter" tutorial, does not work as I thought it should do.
Just using the code from the tutorial (also with a seperate
waffle-filter.xml) there is a nullpointer exception in the in some JAMWiki-code but the authentication works.
I added the code from the waffle-spring-filter-sample index.jsp to check the remote user und his principal. I also get the privileges for ROLE_USER.
But when I use this code in the applicationContext-security.xml of JAMwiki it doesn´t work. getRemoteUser() returns null. But tomcat server returns no exception or warning.
Hopefully someone can check the code, whether there is some issue with one or more beans from the JAMWiki code. My Problem is that I am neither a Spring Framework nor a Waffle specialist. And from my point of view, there should be no issue between these beans.
I also tried to comment the inner part of the <authentication-manager>-Tag, where jamWikiAuthenticationDao is referenced, but it was not the solution for that problem.

My system: Tomcat 7.0.29 / Waffle 1.4 / Spring Security 3.1 / JAMWiki 1.2.0

Million thanks for any help!

applicationContext-security.xml: [WaffleCode] [CommentedWikiCode]

<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:b="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
             http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
	<!--
	This section contains the basic Spring Security configuration settings.  The intercept-url elements
	define what URLs are protected and what permission is required to access those URLs.  The remember-me
	element enables a cookie to be stored to remember user logins across sessions, and the anonymous
	element implements Spring Security's basic anonymous user permissions - note that these will be updated
	by the JAMWikiAnonymousProcessingFilter.
	-->
	<http pattern="/**/Special:RecentChangesFeed" security="none" />
	<http pattern="/**/Special:Setup" security="none" />
	<http pattern="/**/*.jsp*" security="none" />
	<http pattern="/**/jamwiki.css" security="none" />
	<http pattern="/images/**" security="none" />
	<http pattern="/js/**" security="none" />
	<http pattern="/uploads/**" security="none" />
	<http auto-config="false" entry-point-ref="authenticationEntryPoint">
		<!--
		The intercept-url element defines the roles or authentication states that are required
		to access a URL path.  Roles should be comma-delimited.  To restrict pages by user type
		instead of user role the following values can be used:
		  * IS_AUTHENTICATED_ANONYMOUSLY - Allow access to any user.
		  * IS_AUTHENTICATED_REMEMBERED - Allow access to logged-in users or users with a "remember me" cookie.
		  * IS_AUTHENTICATED_FULLY - Allow access to logged-in users.
		To remove all Spring Security processing from a page use the filters="none" attribute.
		-->
		<intercept-url pattern="/**/Special:Account" access="ROLE_REGISTER,IS_AUTHENTICATED_REMEMBERED" />
		<intercept-url pattern="/**/Special:Admin" access="ROLE_SYSADMIN" />
		<intercept-url pattern="/**/Special:Block" access="ROLE_ADMIN" />
		<intercept-url pattern="/**/Special:Edit" access="ROLE_EDIT_EXISTING,ROLE_EDIT_NEW,ROLE_USER" />
		<intercept-url pattern="/**/Special:Import" access="ROLE_IMPORT" />
		<intercept-url pattern="/**/Special:Login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
		<intercept-url pattern="/**/Special:Maintenance" access="ROLE_SYSADMIN" />
		<intercept-url pattern="/**/Special:Manage" access="ROLE_ADMIN" />
		<intercept-url pattern="/**/Special:Move" access="ROLE_MOVE" />
		<intercept-url pattern="/**/Special:Roles" access="ROLE_SYSADMIN" />
		<intercept-url pattern="/**/Special:Translation" access="ROLE_TRANSLATE" />
		<intercept-url pattern="/**/Special:Unblock" access="ROLE_ADMIN" />
		<intercept-url pattern="/**/Special:Upload" access="ROLE_UPLOAD" />
		<intercept-url pattern="/**/Special:Upgrade" access="ROLE_SYSADMIN" />
		<intercept-url pattern="/**/Special:VirtualWiki" access="ROLE_SYSADMIN" />
		<intercept-url pattern="/**" access="ROLE_VIEW,ROLE_USER" />
		<access-denied-handler ref="jamwikiAccessDeniedHandler" />
		<!-- <remember-me key="jam35Wiki" services-alias="_rememberMeServices" /> -->
		<anonymous key="jam35Wiki" />
		<!-- note that the JAMWiki LoginServlet will add the appropriate logout success URL to the request during logout -->
		<logout success-handler-ref="jamwikiLogoutSuccessHandler" />
		<custom-filter position="FORM_LOGIN_FILTER" ref="authenticationProcessingFilter" />
		<custom-filter before="EXCEPTION_TRANSLATION_FILTER" ref="jamwikiPostAuthenticationFilter" />
		<custom-filter ref="waffleNegotiateSecurityFilter" position="BASIC_AUTH_FILTER" />
	</http>
	
	<!--
	The authentication processing filter controls where a user will be sent when he tries to
	access a protected URL and how that user will be authenticated after trying to login.
	-->
	<b:bean id="authenticationProcessingFilter" class="org.jamwiki.authentication.JAMWikiAuthenticationProcessingFilter">
		<b:property name="authenticationManager" ref="authenticationProvider" />
		<b:property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
		<!-- do not include virtual wiki in the url, JAMWikiAuthenticationProcessingFilter adds it -->
		<b:property name="filterProcessesUrl" value="/j_spring_security_check" />
<!-- commented because of exception caused by using waffle and this funktion-->   <!-- <b:property name="rememberMeServices" ref="_rememberMeServices" /> --> </b:bean> <!-- The authentication provider is the element which is passed user login attempts for verification. --> <authentication-manager alias="authenticationManager"> <authentication-provider user-service-ref="jamWikiAuthenticationDao"> <password-encoder ref="jamwikiPasswordEncoder" /> </authentication-provider> </authentication-manager> <b:bean id="jamWikiAuthenticationDao" class="org.jamwiki.authentication.JAMWikiDaoImpl" /> <b:bean id="jamwikiPasswordEncoder" class="org.jamwiki.authentication.JAMWikiPasswordEncoder" /> <b:bean id="authenticationFailureHandler" class="org.jamwiki.authentication.JAMWikiAuthenticationFailureHandler"> <!-- do not include virtual wiki in the url, JAMWikiAuthenticationFailureHandler adds it --> <b:property name="authenticationFailureUrl" value="/Special:Login?message=error.login" /> </b:bean>
<!-- The error message provider adds a page-specific error message to be used when a user is denied access to a page. For example, a different error is shown to users who are not allowed to edit a page than to those who are denied access to the admin pages. --> <b:bean id="jamwikiErrorMessageProvider" class="org.jamwiki.authentication.JAMWikiErrorMessageProvider"> <b:property name="urlPatterns"> <b:map> <b:entry key="/**/Special:Account" value="login.message.account" /> <b:entry key="/**/Special:Admin" value="login.message.admin" /> <b:entry key="/**/Special:Edit" value="login.message.edit" /> <b:entry key="/**/Special:Maintenance" value="login.message.admin" /> <b:entry key="/**/Special:Manage" value="login.message.admin" /> <b:entry key="/**/Special:Move" value="login.message.move" /> <b:entry key="/**/Special:Roles" value="login.message.admin" /> <b:entry key="/**/Special:Translation" value="login.message.admin" /> <b:entry key="/**/Special:Upgrade" value="login.message.upgrade" /> <b:entry key="/**/Special:VirtualWiki" value="login.message.admin" /> <b:entry key="/**/*" value="login.message.default" /> </b:map> </b:property> </b:bean> <!-- This method adds any message from the errorMessageProvider to the redirect. --> <b:bean id="jamwikiAccessDeniedHandler" class="org.jamwiki.authentication.JAMWikiAccessDeniedHandler"> <b:property name="errorMessageProvider" ref="jamwikiErrorMessageProvider" /> </b:bean> <!-- The entry point is the page to which users are redirected when login is required. --> <b:bean id="authenticationEntryPoint" class="org.jamwiki.authentication.JAMWikiAuthenticationProcessingFilterEntryPoint"> <!-- do not include virtual wiki in the url, JAMWikiAuthenticationProcessingFilterEntryPoint adds it --> <b:property name="loginFormUrl" value="/Special:Login" /> <!-- a PortMapper has to be configured if this is true and we are not using default ports --> <b:property name="forceHttps" value="false" /> <b:property name="errorMessageProvider" ref="jamwikiErrorMessageProvider" /> </b:bean> <!-- This filter is executed after the user has been authenticated. It performs two functions: 1. For users authenticated by LDAP or another system, this filter will create the necessary JAMWiki user database records automatically. 2. If anonymous users are allowed then this filter will automatically add the roles from the JAMWiki GROUP_ANONYMOUS group. These roles can be configured through the Special:Roles admin page. Set the useJAMWikiAnonymousRoles property to false if JAMWiki anonymous roles should not be assigned. --> <b:bean id="jamwikiPostAuthenticationFilter" class="org.jamwiki.authentication.JAMWikiPostAuthenticationFilter"> <b:property name="key" value="jam35Wiki" /> <b:property name="useJAMWikiAnonymousRoles" value="true" /> </b:bean> <!-- This logout success handler redirects to the proper default topic and virtual wiki. --> <b:bean id="jamwikiLogoutSuccessHandler" class="org.jamwiki.authentication.JAMWikiLogoutSuccessHandler" /> <!-- Waffle Authentification settings --> <b:bean id="waffleWindowsAuthProvider" class="waffle.windows.auth.impl.WindowsAuthProviderImpl" /> <b:bean id="negotiateSecurityFilterProvider" class="waffle.servlet.spi.NegotiateSecurityFilterProvider"> <b:constructor-arg ref="waffleWindowsAuthProvider" /> </b:bean> <b:bean id="basicSecurityFilterProvider" class="waffle.servlet.spi.BasicSecurityFilterProvider"> <b:constructor-arg ref="waffleWindowsAuthProvider" /> </b:bean> <b:bean id="waffleSecurityFilterProviderCollection" class="waffle.servlet.spi.SecurityFilterProviderCollection"> <b:constructor-arg> <b:list> <b:ref bean="negotiateSecurityFilterProvider" /> <b:ref bean="basicSecurityFilterProvider" /> </b:list> </b:constructor-arg> </b:bean> <b:bean id="negotiateSecurityFilterEntryPoint" class="waffle.spring.NegotiateSecurityFilterEntryPoint"> <b:property name="Provider" ref="waffleSecurityFilterProviderCollection" /> </b:bean> <b:bean id="waffleNegotiateSecurityFilter" class="waffle.spring.NegotiateSecurityFilter"> <b:property name="Provider" ref="waffleSecurityFilterProviderCollection" /> <b:property name="PrincipalFormat" value="fqn" /> </b:bean> </b:beans>

 

Daniel Doubrovkine

unread,
Aug 30, 2012, 10:35:01 AM8/30/12
to waffle...@googlegroups.com
I would first narrow this down to a single HTTP request that should cause authentication. 


_theStudent_

unread,
Sep 3, 2012, 10:52:11 AM9/3/12
to waffle...@googlegroups.com
Hi, thanks for your reply and sorry for my late answer, but I was "out of office" for a few days.
I tried to activate the waffle log (added "waffle.servlet.level = DEBUG" to apache-tomcat-7\conf\logging.properties) but than I realized that starting Tomcat via eclipse means that there is another tomcat instance without this file. For this reason I copied everything into tomcats webapp folder and did it again. But there was no success. It would be perfectly fine to have the debug log as standard output on eclipse console. How do I activate it in this case?

Maybe that is a dumb question but how do I check the www-authetication? I searched for NTLM auditing but there is a warning not to try it on Vista.




Daniel Doubrovkine

unread,
Sep 3, 2012, 12:41:29 PM9/3/12
to waffle...@googlegroups.com
I don't know much about Eclipse and all that, whatever way you can configure logging in Tomcat is the way to go. Waffle is just another JAR in your tomcat instance.

Use web developer tools in any browser to examine the HTTP headers returned. If you're using IE, try IEHttpHeaders (bottom of https://github.com/dblock/waffle/wiki/Troubleshooting-Negotiate has a link and a description).

_theStudent_

unread,
Sep 25, 2012, 6:50:24 AM9/25/12
to waffle...@googlegroups.com
After a break for some other tasks I'm working on this topic again...
I still have not been able to activate the Debug logging for Waffle directly, but there is a logging feature provided by JAMWiki. As both projects are based on spring security framework all the waffle beans were logged when loaded.
So I am sure that all necessary beans/classes were loaded. Than I tried to do an manual login which led me to an 401 (for a valid user login!!!):

Authentication Failed: No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken


So I added these lines to the authentication-manager call:
<authentication-manager alias="authenticationManager">
        <authentication-provider ref="waffleWindowsAuthProvider" />
        <authentication-provider user-service-ref="jamWikiAuthenticationDao" />
</authentication-manager>

Then the server starts with an exception:
Error creating bean with name 'org.springframework.security.authenticationManager': Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)

and a 404.

Can you resolve that exception? Do I have to change anything in the WindowsAuthProviderImpl-class? How does the sample initialize the authenticationProvider, when there is no reference to the bean with the class information?

In general, the combination of waffle-authentication and jamWikiAuthenticationDao for user details service should work, because there are tutorials for using ldap-authentication with this configuration. So I hope the issue is just on waffle side.

Just to make sure: I added localhost:8080 in network.negotiate-auth.trusted-uris to enable SSO for firefox.

To summarize all that stuff:
1. Why is there no waffle logging in any logfile provided by tomcat? Is adding "waffle.servlet.level = DEBUG" to apache-tomcat-7\conf\logging.
properties not the right way or just not enough?

2. Do I have to add anything to WindowsAuthProviderImpl-class to prevent the describe exception?

Thanks again for any help!
br
Manuel

Daniel Doubrovkine

unread,
Sep 25, 2012, 11:55:01 AM9/25/12
to waffle...@googlegroups.com
Logging. I don't know. Since this is a Spring application, who knows what happens. I bet there's a different place where you need to configure logging, but I am not a Spring expert.

What you want to do is definitely possible. But Spring is a beast and there're a lot of moving parts and it was designed to be extensible, not easy :)

What you should focus on is getting the initial 401 from Waffle here with the correct HTTP headers (WWW-Authorization: NTLM) and dump any kind of other spring authenticators in place, first. Check out the integration in spring examples in https://github.com/dblock/waffle/tree/1.5/Source/JNA/demo, hopefully they will provide some configuration insight - I also wrote http://code.dblock.org/single-sign-on-spring-security-negotiate-filter-kerberos-ntlm-wwaffle a while ago that talks about how this was constructed. 

The fact that you have a UsernamePasswordAuthenticationToken there is already saying that you're mising SSO and non-SSO auth, which is not possible (at least not yet :)).

_theStudent_

unread,
Dec 6, 2012, 10:28:27 AM12/6/12
to waffle...@googlegroups.com
Hello Mr. Doubrovkine,

after some longer discussions with the jamwiki side, I found all issues (hopefully ;)) preventing me from editing articles with a SSO authentication. At least I managed to access pages secured against any user without ROLE_USER. The next problem was to enable login for users with "\"
 in it, as your SSO returns the FQN of a user. This also works now.
The last problem I found is a hardcoded check for ROLE_EDIT_EXISTING and ROLE_EDIT_NEW when ever a page is loaded via a method called isEditable().
It would be hard to edit this part of JAMWiki because it I am using the war file where the part to edit is only added with a jar, not the source folder from respository. I tried to run/build it from source files, but - as I am not a maven specialist or at least a basic user ;) - this won't work as I want it.
Long story short: Can you tell me, where I can add the roles above to the authentication? I will try to biuld it from source files simultaneous
That would be great!
Best regards,
Manuel

Daniel Doubrovkine

unread,
Dec 6, 2012, 11:01:36 AM12/6/12
to waffle...@googlegroups.com
These roles are added via https://github.com/dblock/waffle/blob/master/Source/JNA/waffle-spring-security3/src/waffle/spring/FqnGrantedAuthorityFactory.java - this is setup to add groups as you describe by default. I would try to replace this with your own  token granting authority via Spring configuration (that could derive from this implementation). In theory you shouldn't need to rebuild Waffle at all to do this, you can just inject your class in place.

Daniel Doubrovkine

unread,
Dec 6, 2012, 11:07:44 AM12/6/12
to waffle...@googlegroups.com
I may have slightly mislead you. The authorities are added here: https://github.com/dblock/waffle/blob/master/Source/JNA/waffle-spring-security3/src/waffle/spring/WindowsAuthenticationToken.java#L74 . This might need a bit of work to be extended to add other things.

_theStudent_

unread,
Dec 11, 2012, 5:24:28 AM12/11/12
to waffle...@googlegroups.com
Hi,

no problem, I anticipated as much. I will try to extend it, but maybe at this point working with the sources would be a better idea than to extend all necessary classes, because the WindowsAuthenticationToken is not called directly from config.xml.

I will report, whether I succeeded and how.

Best regards


Reply all
Reply to author
Forward
0 new messages