How Do I get proper error messages from Spring Security UI? - grails

I have been using spring security UI and spring security plugin. We have our register.gsp page which works as expected. We are moving our css to twitter bootstrap so we changed register.gsp file, to match our requriements.
So we changed :
<s2ui:textFieldRow name='username' labelCode='user.username.label' bean="${command}"
size='40' labelCodeDefault='Username' value="${command.username}"/>
To :
<g:textField class="input-large" bean="${command}" name="username"
value = "${command.username}" required = "" />
Now the problem is how I render error messages? I get only default error message as now :
Property {0} ... doesn't pass custom validation.
Actually I need to get the error message of what Spring Security UI offered. How can I do that?
Thanks in advance.

You can to use:
<g:textField class="input-large" bean="${command}" name="username"
value = "${command.username}" required = "" />
<g:eachError bean="${command}">
<span>${it}</span>
</g:eachError>

Related

JSF FacesMessage shows detail message instead of summary message

I am not clear on how addMessage() and FacesMessage works. If I didnt specify a <h:message> for it to display a message, the summary message will be displayed. But if I create a <h:message> field for it, the detailed message will be displayed. Why? How to select which message to display? Below is my code:
Bean
public String login()
{
if(password.equals("123123"))
{
session.setAttribute("username", username);
return "home";
}
else
{
FacesContext.getCurrentInstance().addMessage("loginForm", new FacesMessage(FacesMessage.SEVERITY_WARN,"Incorrect Username and Passowrd", "Please enter correct username and Password"));
return "login";
}
}
JSF
<h:form id="loginForm">
<h:outputLabel for="username" value="Username: " />
<h:inputText id="username" value="#{loginBean.username}" required="true" requiredMessage="Username is required" />
<h:message for="username"></h:message>
<br /><br />
<h:outputLabel for="password" value="Password: " />
<h:inputSecret id="password" value="#{loginBean.password}"></h:inputSecret>
<h:message for="password"></h:message>
<br /><br />
<h:commandButton action="#{loginBean.login()}" value="Login"></h:commandButton>
<br /><br />
</h:form>
The code above will produce the following output:
But if I add <h:message for="loginForm"></h:message> into my code, the output will be:
It shows the detailed message instead of summary message, it is not a big deal actually but I just want to know why this happens? Can anyone explain?
That orange message will only appear when you have javax.faces.PROJECT_STAGE set to Development and you forgot to declare a <h:messages> in the view. In such case JSF can't show the message anywhere in the page. Normally, this is only logged as a warning in server log like so:
There are some unhandled FacesMessages, this means not every FacesMessage had a chance to be rendered
However, for developer's convenience this is also appended to the end of the webpage when project stage is set to development. But you should not rely on that as normal functionality of the webapp. You should take that as a hint that you overlooked something or did something wrong. The correct solution would be to add an appropriate <h:message for="xxx"> or at least a <h:messages> as fallback.
That the development stage message shows the summary instead of the detail is your least concern. It should in first place not have been displayed at all.
See also:
How to use JSF h:messages better?

Grails 3 CSRF protection

Is it possible to configure CSRF protection in grails3 app using spring-security plugin, I can't find anything except useToken attribute for grails form and then call withForm inside controller. But this is actually not a very flexible solution. I like approach with filter like here
For csrf protection I reused org.springframework.security.web.csrf.CsrfFilter. You need to define new bean in grails resouces.groovy (See snipet below - csrfFilter bean). You can define your own accessDeniedHandler and requireCsrfProtectionMatcher. Here is the snippet from resources.groovy:
csrfFilter(CsrfFilter, new HttpSessionCsrfTokenRepository()) {
accessDeniedHandler = ref('fnAccessDeniedHandler')
requireCsrfProtectionMatcher = ref('fnRequireCsrfProtectionMatcher')
}
Now in Bootstrap.groovy add this filter into filter chain:
SpringSecurityUtils.clientRegisterFilter('csrfFilter', SecurityFilterPosition.LAST.order + 10)
Now in your main layout GSP add following tags to add csrf token on each page:
<meta name="_csrf" content="${_csrf?.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf?.headerName}"/>
So now csrf token presented on each page of your app, you can use it for each ajax request for example (snippet from application.js (I'm using grails 3)):
$(function () {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
For each jquery ajax request we are sending csrf token now.
You can implement it with <g:form> tag:
Example:
<g:form useToken="true" uri="/logout">
Documentation: http://grails.github.io/grails-doc/latest/guide/single.html#formtokens
In my case, I'm using Spring code, so, additionally, I should add manually a _csrf hidden field in the form.
<g:form useToken="true" uri="/logout">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="submit">Logout</input>
</g:form>
Result:
<form action="/nacho/logout" method="post" >
<!-- this two lines are added automatically by Grails -->
<input type="hidden" name="SYNCHRONIZER_TOKEN" value="883a1037-a2c9-4997-8254-e59da6303494" id="SYNCHRONIZER_TOKEN" />
<input type="hidden" name="SYNCHRONIZER_URI" value="/nacho/userInfo" id="SYNCHRONIZER_URI" />
<!-- this line was added by myself, but, using the ${_csrf} variable -->
<input type="hidden" name="_csrf" value="0928f13c-02aa-4122-8ebe-a1239855a85b"/>
<input type="submit">Logout</input>
</form>

Expected CSRF token not found. Has your session expired? + Spring security + CSRF

I am trying to implement CSRF via spring security.
But, facing following error in browser, after clicking login button(from home.jsp)
"Expected CSRF token not found. Has your session expired?"
I have following configuration in
spring-security-config.xml:
<http auto-config="false">
<csrf/>
</http>
home.jsp:
<form action="j_spring_security_check" id="LoginForm" method="post">
<input type="text" title="Username" name="j_username" id="j_username"
class="inset-shadow defaultText" placeholder="Username" />
<input type="password" title="Password" name="j_password"
id="j_password" class="inset-shadow defaultText" placeholder="Password" />
<input type="submit" class="submit" title="LOGIN"
onsubmit="javascript:{loginSubmit();}"/>
<input type="hidden" name="_csrf" value="dc7ce2be-f73b-4086-8f90-8ef00b8f81d5"/>
</form>
Error from jboss server.log:
2015-09-14 19:56:10,221 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/].[jsp]] (http-127.0.0.1-8190-2) Servlet.service() for servlet jsp threw exception: java.lang.IllegalStateException: getAttribute: Session already invalidated
at org.apache.catalina.session.StandardSession.getAttribute(StandardSession.java:1024) [:6.1.0.Final]
at org.apache.catalina.session.StandardSessionFacade.getAttribute(StandardSessionFacade.java:110) [:6.1.0.Final]
at org.apache.jsp.WEB_002dINF.jsp.home_jsp._jspService(home_jsp.java:99)
Note : Not sure whether the error from server.log relates to CSRF
Any help on this problem is highly appreciated?
Instead of
<input type="hidden" name="_csrf" value="dc7ce2be-f73b-4086-8f90-8ef00b8f81d5"/>
did you try
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
As per the docs, the csrf and token would be computed by Spring and appended as a request parameter, with name as ${_csrf.parameterName} and value as ${_csrf.token}.
I had the same error.
I my case, the html page containing the form have a link tag to a css file into my web application.
This link to css file has been also protected by spring security and due to this, I had your error.
When I unprotect link to css file, no error occur.
This is an example how to unprotect files in Spring Security with Java Config
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**");
}

File upload & Spring Security

Based on the Spring Security documentation, I setup a MultipartFileter as the following:
#Order(1)
public class SecurityWebAppInitializer
extends AbstractSecurityWebApplicationInitializer {
#Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
insertFilters(servletContext, new MultipartFilter());
}
In a file upload form, I can see a CSRF input with a not-null value in a HTML file (see the code below).
<form method="POST" enctype="multipart/form-data" action="/upload">
File to upload: <input type="file" name="file" /><br />
Name: <input type="text" name="name" /><br /> <br />
<input type="submit" value="Upload" />
Press here to upload the file!
<input type="hidden" name="_csrf" value="df94be7d-675d-428c-89e5-2ebf0b473c42" />
</form>
After submitting the form, I get an error as
HTTP Status 403 - Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.
type Status report
message Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.
description Access to the specified resource has been forbidden.
What is missing here?
This problem is resolved after changing the Java configuration of the application. The followings are those changes.
In AbstractAnnotationConfigDispatcherServletInitializer class, I add the MultipartFilter in the getServletFilters method and set the MultipartConfig with a MultipartConfigElement in customizeRegistration(ServletRegistration.Dynamic registration) method. A MutlipartConfigElement originally defined in WebMvcConfigurerAdapter class is removed. And a MultipartResolver defined in the class is unchanged.
The Java configuration was set up based on the original XML configuration of the application. The approach doesn't always work based on this case.

Build-in Grails tags do not work

During grails application upgrade from 1.3.8 to 2.3.9 I run into the problem that grails build-in tags are ignored.
For example lets say that GSP page has two tags:
<g:if test="${true}">OK</g:if>
<g:hiddenField name="test" />
then the result of execution will be:
OK
<g:hiddenField name="test" />
but expected result is :
OK
<input type="hidden" name="test" />
Basically tags from grails-web-2.3.9.jar are working fine but from grails-plugin-gsp-2.3.9.jar are completely ignored.
Any clue why this happens is appreciated. Thank you.
UPDATE:
I found that while executing TagLibraryLookup.afterPropertiesSet() method grailsApplication object is null, so the tag lib is not registered. Now it is not clear why it is null...
Solotion:
The problem was that within static constraints = { } of domain object it was a call of
ApplicationHolder?.getApplication().getMainContext()?.getBean(serviceName) method. It prevented the application from initialization of all required spring/grails beans by changing initialization sequence/flow.
You're missing some double-quotes here:
<g:if test=${true}>OK</g:if>
<g:hiddenField name="test" />
If you add them:
<g:if test="${true}">OK</g:if>
<g:hiddenField name="test" />
Does that help? Also, check for any changes to the default encoding that was made in Config.groovy after you upgraded.

Resources