Getting 400 Bad Request with Grails Spring Security Rest Plugin - spring

I'm trying grails restful spring security rest plugin.
I'm using Grails 2.5.2 with spring-security-rest:1.5.2.
I'm unable to make login work with the following ajax call. I get 400 bad request. But if I try to use CURL command it works! I don't understand what's wrong.
That's the ajax post call:
var config = {
type : 'POST'
,url : '/api/login'
,data : {username:"xxxx",password:"xxxx"}
,async : false
,dataType : 'JSON'
,contentType: "application/json;charset=utf-8"
,success: function(response) {
console.dir(response);
}
,error : function (response) {
console.dir(response);
}
}
$.ajax(config);
Spring rest plugin configuration inside Config.groovy is:
grails.plugin.springsecurity.filterChain.chainMap = [
'/api/**': 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter', // Stateless chain
'/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter' // Traditional chain
]
grails.plugin.springsecurity.rest.login.active=true
grails.plugin.springsecurity.rest.login.failureStatusCode=401
grails.plugin.springsecurity.rest.token.validation.active=true
This is my curl command:
curl -i -X POST -H "Content-Type: application/json" -d '{"username":"xxxxx", "password":"xxxx"}' http://localhost:8080/api/login
and that's the response:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Content-Length: 2172
Date: Tue, 01 Mar 2016 13:28:42 GMT
{"username":"xxxxxx","roles":["ROLE_ADMIN"],"token_type":"Bearer","access_token":"eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NTY4NDI1MjIsInN1YiI6ImFkbWluZGllIiwicHJpbmNpcGFsIjoiSDRzSUFBQUFBQUFBQUpWU3YwOFVRUlIrZXg2QlNLSmdnb2tGTm1KbjloTG92RWJBMDJDV3czQmNnNGxrYnZleERqYzdzODdNSG5jTnVVb0xDZ2hJWXVLXC93SDhpalgrQWdZS1cydFkzeThFZU5JU3BkdDk4Kzczdnh4NWZ3SWpSTUJkcnhvWHhVNUhGWFBvbTFWekdCc05NYzl2ek00TTZRcHNqM3VmQUprM2c4bmdsOEFJbzhjakNrMkNMZFZoRk1CbFhWbHBiR05wcVY4T3MwdkdBY1ZPekJMZVZidnZYM0tIU2VHTkJRZTI5S2NIb09reXlNRlNadEhVb................... etc.etc.
Any help is really appreciated!

Basing on official docs you should change dataType to 'json':
dataType (default: Intelligent Guess (xml, json, script, or html))
btw did you try to remove async : false from config and check it?

Related

Curl lets me GET but does not let me POST ... Spring JPA

When I run the Spring Application and then try to comunicate with
the REST API it allows me to GET but not to POST.
So this works:
curl -u user:a75fd7ea-9a6e-4943-bc0c-3b0a96bda51b http://localhost:5000/activity/getall
This does not work:
curl -u user:a75fd7ea-9a6e-4943-bc0c-3b0a96bda51b
-H "Accept: application/json"
-X POST
-d '{
"name":"Sleep",
"criteria":"Sleep at least 8 hrs",
"ini":"2022-08-30",
"periodicity":"DAY",
"periodicityCount":"1"
}'
http://localhost:5000/activity/post
If you notice is the same Username and Password.
This is the response I get:
HTTP/1.1 403
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json
Transfer-Encoding: chunked
Date: Mon, 29 Aug 2022 19:25:27 GMT
Connection: close
{
"timestamp": "2022-08-29T19:25:27.510+00:00",
"status": 403,
"error": "Forbidden",
"path": "/activity/post"
}
The reason why your API calls fail is due to the CSRF protection you enabled in your Spring Security configuration.
The way this works is that for each non-GET request (= POST, PUT, PATCH or DELETE), you need to include a CSRF token.
To obtain a CSRF token, you first need to fire a GET request (eg. http://localhost:5000/activity/getall). In the response headers, you should see a Set-Cookie header containing an XSRF-TOKEN cookie. For example:
Set-Cookie: XSRF-TOKEN=098b732a-282a-11ed-a261-0242ac120002
Now you need to copy the value of the XSRF-TOKEN cookie (should contain a UUID), and set it as the value of the X-XSRF-TOKEN header:
curl \
-u user:a75fd7ea-9a6e-4943-bc0c-3b0a96bda51b
-H "Accept: application/json"
-H "X-XSRF-TOKEN: 098b732a-282a-11ed-a261-0242ac120002"
-X POST \
-d '{
"name":"Sleep",
"criteria":"Sleep at least 8 hrs",
"ini":"2022-08-30",
"periodicity":"DAY",
"periodicityCount":"1"
}'
http://localhost:5000/activity/post
After that, your request should succeed. Be aware, the response of this POST-request will contain a new CSRF token that you will have to copy to your next request.
Alternatively, you can disable CSRF protection by setting .csrf().disable() in your Spring Security configuration.

How to login into a Laravel app using cURL

I want to setup a small file of cURL requests so I can quickly test my Laravel app's API quickly.
Unfortunately, I'm stuck at logging in :D.
This is what I have so far:
curl -H "Accept: application/json" -d #./curl/user.json http://localhost:8000/login -o ./curl/response.json -v
I have a user.json file that has my login info:
{
"email": "boss#example.com",
"password": "password",
}
And I would like to output the data into my response.json file.
Nothing is working though. I have a poor understanding of a couple of these technologies. Anyone able to hold my hand through this?
With the -v tag, I'm getting:
connect to ::1 port 8000 failed: Connection refused
* Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> POST /login HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.77.0
> Accept: application/json
> Content-Length: 81
> Content-Type: application/x-www-form-urlencoded
>
} [81 bytes data]
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Host: localhost:8000
< Date: Mon, 17 Jan 2022 01:47:53 GMT
< Connection: close
< X-Powered-By: PHP/7.4.27
< Cache-Control: no-cache, private
< Date: Mon, 17 Jan 2022 01:47:53 GMT
< Content-Type: application/json
< Set-Cookie: laravel_session=eyJpdiI6IkpoUkhoQnNWdEVhYUdGU2wzckg5c3c9PSIsInZhbHVlIjoidGwrUHpBcDV4Z2lXNWdObmQrdER2OUp0aEIveXhpdFNREmovedSomeSTufffForSecurityPurposesmNyb3oiLCJtYWMiOiIyZTY2Yzk1MWY3MDA3M2I3NDkzMmQzMTUwMjcyNDFmMTU3MTU
0MzRmZjAzNDBjZmZmZTgwMjg1MjMzOThkZmU5IiwidGFnIjoiIn0%3D; expires=Mon, 17-Jan-2022 03:47:53 GMT; Max-Age=7200; path=/; httponly; samesite=lax
<
Any idea how I can login to a Larvel app using cURL? The goal is to make it work like Postman, but in the terminal!
I want to setup a small file of cURL requests so I can quickly test my Laravel app's API quickly.
Any idea how I can login to a Larvel app using cURL? The goal is to make it work like Postman, but in the terminal!
Login using Laravel's default authentication page and API authentication are two different things. I can't explain to you about API authentication in depth, as it would be quite lengthy.
Laravel has two packages that you can use for this case, Passport and Sanctum.
Sanctum is automatically installed when you install Laravel.
Since middleware on web is different from API, you should focus on route routes/api.php. You can create a token generation route (same as login). For example :
Route::post('/token', function (Request $request) {
// You can replace it with your login logic
$user = User::first();
$token = $user->createToken('Your Awesome Token Name');
return ['token' => $token->plainTextToken];
});
Return :
{
"token": "1|jLw1HhWJhSVQq81VFZwhxYB93GKMl5JRCrtuYQ36"
}
Then, the generated token you can use to access other API routes.
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
Calling via cURL :
curl -i http://your-awesome-app.test/api/user -H "Authorization: Bearer <TOKEN>"
Change <TOKEN> :
curl -i http://your-awesome-app.test/api/user -H "Authorization: Bearer 1|jLw1HhWJhSVQq81VFZwhxYB93GKMl5JRCrtuYQ36"
Viola!!!
{
"id":1,
"name":"Your Awesome User",
"email":"your.awesome#user.test",
"email_verified_at":"2022-01-17T03:03:58.000000Z",
"created_at":"2022-01-17T03:03:58.000000Z",
"updated_at":"2022-01-17T03:03:58.000000Z"
}

Ambari api POST complaining CSRF protection

I am trying to set hbase property through Ambari API using following command
curl -u "admin:admin" -i -X POST -d '{"type": "hbase-site", "tag": "version3", "properties" : {"hbase.regionserver.global.memstore.size" : "0.6"}}' https://abct.net/api/v1/clusters/xyz/configurations
But keep getting following error
HTTP/1.1 400 Bad Request
Content-Length: 107
Content-Type: text/plain
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Server: Microsoft-IIS/8.5
x-ms-hdi-active: 10.8.18.29
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
User: admin
X-Powered-By: ARR/3.0
Set-Cookie: AMBARISESSIONID=2e8ortl32j1p7zdjatigdgvg;Path=/;HttpOnly; path=/; secure
X-Powered-By: ASP.NET
Date: Mon, 12 Sep 2016 18:19:38 GMT
{
"status" : 400,
"message" : "CSRF protection is turned on. X-Requested-By HTTP header is required."
}
What am missing here ?
Turns out you have to add the request header to the request for anything other than a GET request.
You can add the header with
curl --header "X-Requested-By: my_computer_name"
Or
You can disable this feature.
I had same problem in c# Rest client. Using Brig's answer fixed it:
HttpClientHandler handler = new HttpClientHandler
{
Credentials = new System.Net.NetworkCredential("xxxx", "yyyyy"),
};
using (var httpClient = new HttpClient(handler))
{
//"X-Requested-By: my_computer_name"
httpClient.DefaultRequestHeaders.Add("X-Requested-By","my_computer_name");

Post request to golang server using polymer core-ajax?

I am trying to make a POST request using polymer core-ajax to server runnung golang. After a lot of search (because i am new to this stuff) i ended up with the following code. Also, GET request is working perfect. POST parameters i dont understand how to pass using core-ajax.
<polymer-element name="register-user" attributes="url">
<template>
<core-ajax id="ajaxSubmit" url="{{url}}" contentType="application/json" handleAs="json" method="post" on-core-response="{{response}}"></core-ajax>
<style type="text/css">
</style>
</template>
<script>
Polymer({
buttonListener: function() {
var data = '{"Name":"'+ this.name +'", "Email":"'+ this.email +'"}';
this.$.ajaxSubmit.data = data;
this.$.ajaxSubmit.go();
console.log(data);
},
response: function(oldValue){
console.log(this.response);
}
});
</script>
</polymer-element>
above code returns 500 (Internal Server Error) however when i make a POST request using curl i.e
curl -i -H 'Content-Type: application/json' -d '{"Name":"Batman",
"Email":"batman#gmail.com"}' http://so.me.ip.ad:8080/register
it works as it should and returns
HTTP/1.1 200 OK
Content-Type: application/json
X-Powered-By: go-json-rest
Date: Wed, 29 Apr 2015 05:40:15 GMT
Content-Length: 117
{
"id": 3,
"name": "Batman",
"email": "batman#gmail.com",
"createdAt": "2015-04-29T05:40:15.073491143Z"
}
also, i have a CORS middleware set up on server i.e
api.Use(&rest.CorsMiddleware{
RejectNonCorsRequests: false,
OriginValidator: func(origin string, request *rest.Request) bool {
return origin == "http://0.0.0.0:8000"
},
AllowedMethods: []string{"GET", "POST", "PUT"},
AllowedHeaders: []string{
"Accept", "Content-Type", "X-Custom-Header", "Origin"},
AccessControlAllowCredentials: true,
AccessControlMaxAge: 3600,
})
What am i doing wrong? Any feedback will be of great help! Thanks ^.^
Edit : here is a little more info if it can help..
I think CORS is a red herring. The problem may be that you are sending the data form-encoded and not as json. I found a bug from a user with a similar problem.
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
X-Powered-By: go-json-rest
Date: Fri, 12 Dec 2014 04:29:59 GMT
Content-Length: 71
{
"Error": "invalid character '\\'' looking for beginning of value"
}
Perhaps you should use .body instead of .data? See this answer.
From the polymer documentation:
body: Optional raw body content to send when method === "POST".
Example:
<core-ajax method="POST" auto url="http://somesite.com"
body='{"foo":1, "bar":2}'>
</core-ajax>

Problem with Spring 3 + JSON : HTTP status 406?

I'm trying to get a list of Cities by sending the State name through Ajax in my SpringMVC 3.0 project.
For the purpose, I've used the following call (using jQuery) in my JSP:
<script type="text/javascript">
function getCities() {
jq(function() {
jq.post("getCities.html",
{ stateSelect: jq("#stateSelect").val()},
function(data){
jq("#cities").replaceWith('<span id="cities">Testing</span>');
});
});
}
</script>
And here's my Controller code:
#RequestMapping(value = "/getCities", method = RequestMethod.POST)
public #ResponseBody List<StateNames> getCities(#RequestParam(value="stateSelect", required=true) String stateName,
Model model) {
// Delegate to service to do the actual adding
List<StateNames> listStates = myService.listCityNames(stateName);
// #ResponseBody will automatically convert the returned value into JSON format
// You must have Jackson in your classpath
return listStates;
}
But I get HTTP 406 error stating the following when i run it:
406 Not Acceptable
The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.
I've used Jackson in my Maven dependencies & have defined in my context file.
I've googled extensively & I guess the problem is #ResponseBody is not automatically converting my List to appropriate JSON object.
My Firebug says:
Response Headers
Server Apache-Coyote/1.1
Content-Type text/html;charset=utf-8
Content-Length 1070
Date Sat, 12 Feb 2011 13:09:44 GMT
Request Headers
Host localhost:8080
User-Agent Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13
Accept */*
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
Content-Type application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With XMLHttpRequest
Referer http://localhost:8080/MyApplication/
Content-Length 17
Cookie JSESSIONID=640868A479C40792F8AB3DE118AF12E0
Pragma no-cache
Cache-Control no-cache
Please guide me. What am i doing wrong?? HELP!!
As Peter had written in his comment, the cause of the problem is inability of Spring to load Jackson. It is not loaded by dependencies by default. After I've added the dependency
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.2</version>
</dependency>
the JSON was returned after typing the address in the browser, without any tricks with Accept headers (as it is supposed to do).
Tested on Tomcat 7.0.
You have incorrect response content type it supposed to be application/json.
You need to add jackson to your /lib directory.
and you should have
<mvc:annotation-driven />
In your serlvet-name.xml file.
In addition I recommend you to map your request as get and try to browse it with Google Chrome,to see if it returns correct result. It has very good json representation.
The problem is not on server side, but on the client one.
Take a look at the error message carefully: The requested resource (generated by server side) is only capable of generating content (JSON) not acceptable (by the client!) according to the Accept headers sent in the request.
Examine your request headers:
Accept */*
Try this way:
function getCities() {
jq(function() {
jq.post(
"getCities.html", // URL to post to
{ stateSelect: jq("#stateSelect").val() }, // Your data
function(data) { // Success callback
jq("#cities").replaceWith('<span id="cities">Testing</span>');
},
"json" // Data type you are expecting from server
);
});
}
This will change your Accept header to the following (as of jQuery 1.5):
Accept: application/json, text/javascript, */*; q=0.01
This will explicitly tell the server side that you are expecting JSON.
Using jQuery , you can set contentType to desired one (application/json; charset=UTF-8' here) and set same header at server side.
REMEMBER TO CLEAR CACHE WHILE TESTING.
I too had a similar problem while using the Apache HTTPClient to call few services. The problem is the client and not the server. I used a HTTPRequester with header accepting application/json and it worked fine.

Resources