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/**");
}
Related
I am new to Brightspace and been fiddling with the remote plugins sample (logo). I can load the sample logo project, but cannot get it to insert into the page. I have uploaded the file but get a 404 error on submit. Can someone `
$( document ).ready(function() {
$('#submitFormButton').click( function() {
$.ajax({
url: "/getisfdetails",
data: {
image: $("input[name='image']:checked").val()
},
success: function(response){
$("input[name='lti_message_type']").val(response.lti_message_type);
$("input[name='lti_version']").val(response.lti_version);
$("input[name='content_items']").val(response.content_items);
$("input[name='oauth_version']").val(response.oauth_version);
$("input[name='oauth_nonce']").val(response.oauth_nonce);
$("input[name='oauth_timestamp']").val(response.oauth_timestamp);
$("input[name='oauth_consumer_key']").val(response.oauth_consumer_key);
$("input[name='oauth_callback']").val(response.oauth_callback);
$("input[name='oauth_signature_method']").val(response.oauth_signature_method);
$("input[name='oauth_signature']").val(response.oauth_signature);
$("#isfForm").prop('action', response.lti_return_url);
$("#isfForm").submit();
}
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<body>
<h3>Select an logo:</h3>
<input type="radio" name="image" value="brightspace-logo.png"> <img src="../content/isf/brightspace-logo.png" alt="Brightspace Logo"><br />
<input type="radio" name="image" value="d2l-logo.png"> <img src="../content/isf/d2l-logo.png" alt="D2L Logo"><br />
<div hidden>
<form id="isfForm" method="POST">
<input type="hidden" name="lti_message_type" />
<input type="hidden" name="lti_version" />
<input type="hidden" name="content_items" />
<input type="hidden" name="oauth_version" />
<input type="hidden" name="oauth_nonce" />
<input type="hidden" name="oauth_timestamp" />
<input type="hidden" name="oauth_consumer_key" />
<input type="hidden" name="oauth_callback" />
<input type="hidden" name="oauth_signature_method" />
<input type="hidden" name="oauth_signature" />
</form>
</div>
<br />
<button id="submitFormButton">Submit</button>
</body>
` how do you set this cookie in the javascript? I believe a cookie needs to be set??? and I do not see how to set it? or maybe I am missing something else that is not noted in the documentation.
I would highly recommend you consider using LTI Advantage/1.3 instead of Remote Plugins. LTI provides a standards-based integration approach & a better developer experience.
https://community.brightspace.com/s/article/LTI-Integration-Guide
If you are working with a partner of D2L please get in touch with the partner team and technical assistance is available. Your information here is appreciated but we are glad to examine the full context and use case as these errors are not hugely uncommon during dev. Otherwise, I echo Paul's suggestion, but I understand if it is not immediately possible.
partners#d2l.com or talk with your team that knows D2L!
Depending on which browser you are in you might be seeing the recent effects of the third-party cookie blocking that the browsers are adopting. Because LTIs (both 1.1 and 1.3/Advantage) typically launch into iframe any access to those cookies are regarded as third party. This effectively means two things
You need to be aware of the cookie access routines where a user action must be taken to request access to the browser storage API using document.requestStorageAccess()
You need to be marking your cookies appropriately with the new SameSite cookie directives
Without these the browser will mark your cookie request as a 'Tracking cookie' and refuse to serve it along with the request or make it accessible via javascript.
An alternative is also to detect that the LTI launch is happening inside the an iframe and to bust that iframe out to a new window, or alternatively configure the launch inside Brightspace to not use a iframe at all.
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>
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.
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>
I've been trying in vain for 2 days now to do a simple upload to my Amazon S3 Bucket. Below is my rendered form:
<form action="http://s3.amazonaws.com/MYBUCKETNAME" method="post" enctype="multipart/form-data">
<input type="hidden" name="AWSAccessKeyId" value="MYACCESSKEY" />
<input type="hidden" name="acl" value="private" />
<input type="hidden" name="key" value="UserUploads/TestUser/${filename}" />
<input type="hidden" name="success_action_redirect" value="http://WWW.MYURL.COM/" />
<input type="hidden" name="policy" value="POLICY" />
<input type="hidden" name="signature" value="SIGNATURE" />
<div>
Please specify a file, or a set of files:
<input type="file" name="file" size="100" />
</div>
<input type="submit" value="Upload" />
</form>
and my policy document looks like this:
{
expiration = "2011-12-08T12:00:00.000Z",
conditions = [
["eq","bucket","MYBUCKETNAME"],
["eq","acl","private"],
["starts-with","$key","UserUploads/TestUser/"],
["eq","success_action_redirect", "HTTP://WWW.MYURL.COM/"]
]
}
I get the following error:
Code: AccessDenied,
Message: Invalid according to Policy: Policy Condition failed: ["eq", "bucket", "MYBUCKETNAME"]
Does anyone have any ideas please, I'm grabbing at straws here. Also not sure if my Bucket Policy and ACL is correct.
According to http://doc.s3.amazonaws.com/proposals/post.html#Access_Control
Matching a Particular Value
Description: There are certain fields that you want to match a
particular value, such as matching a bucket name or requiring that an
object is uploaded using the public-read access control policy. The
field value is case sensitive, but the name is not.
Syntax: There are two ways to require that the field fieldname matches
the string value. The value is case sensitive. If the value starts
with a dollar sign ($), the dollar sign must be escaped with a
backslash (\$)
[ "eq", "$fieldname", "S" ],
(Note the $ prefix).
So your policy should have $ in sets where you using "eq" format
Why not do this in C# with the S3 SDK (http://aws.amazon.com/sdkfornet/), it's a bit more secure.
Here's my blog post with more detail: http://bradoyler.com/post/3614362044/uploading-an-image-with-aws-sdk-for-net-c.
Cheers and Good luck.
I was getting the following error:
Invalid according to Policy: Policy Condition failed: [\"eq\", \"$bucket\"
After many hours, I learned that you can't have a bucket with uppercase letters. Changing the bucket to lowercase fixed it.