Codeigniter CSRF response format - json

I am using a predefined response format for all my ajax calls.
If the request is success then the server will respond :
{"status":true,"data":{"name":"person","age":2}}
Please note data is not necessary.
and if the request failed then i will get
{"status":false,"reason":"You are not authorised."}
SO every response have a status field , if status is FALSE then there will be reason field.
The problem is that now i enables CSRF protection in Codeigniter and if the token expired/failed the system outputs
The action you have requested is not allowed.
this is HTML content.
Is it possible to extend the security class ,so that if the request is through Ajax then it will keep json_encoded format else use the html format.(i do not want to modify the core)
Thanks.

This error message is rendered from the CI_Exceptions::show_error method (located in system/core). You can extend this class by the usual way and override this method in order to catch this error and return whatever you want.
You can get rid of the call inside the CI_Security::csrf_show_error method by overriding it so it won't simply call
show_error('The action you have requested is not allowed.');
This is probably more robust.
Alternatively you can attack this inside CI_Exceptions class. Since this errors doesn't come with specific error code you will have to match for the message which could break between updates (currently hardcoded). The resulting class could look like this:
class MY_Exceptions extends CI_Exceptions {
public function show_error($heading, $message, $template = 'error_general', $status_code = 500) {
if ($message == 'The action you have requested is not allowed.') {
// handle this error your way
} else {
// send every other error to the original handler
parent::show_error($heading, $message, $template, $status_code);
}
}
}

Related

Text Response from Spring REST API endpoint, how to retrieve that on Angular Front end

Spring REST API is responding with following response:
On successful execution : It returns me a response of Text type.
On unsuccessful execution : It returns me JSON error object.
Front-End Service Class :
private detailsURL = 'http://localhost:8080/register';
constructor(private http:HttpClient){}
register(regisDetails): Observable<any>{
return this.http.post(this.detailsURL,regisDetails);
}
Front-End Component Class:
registerUser(){
this.service.register(this.regisForm.value).subscribe(
success => this.successMessage = success,
error => this.errorMessage = error.error.errorMessage
);
}
In case of error I'm getting the error message I'm supposed to get. But in case of success I'm not getting the successMessage.
Just wanted to know if there's any way to fetch the Text type response on front end. Or else I'll have to change my backend to send response of JSON Type for successful execution as well.
Please help me understand this thing.
You have to set the status for your response. In the controller part you have to mention consumes="application/json" in api request.
You should be doing your changes at the backend and provide the response in Json format response for both the success and backend. That would be the ideal solution.
It is really a bad design to provide a different response than what is expected. You could check the value of the header in request "accept:application/json" and provide response as was expected by the front end
Front End Fix :
However, in the front end you could always use
JSON.parse(success) to convert the text to Json object and use it further as required.

How can I make Feathers (Express-based API Framework) Return Error Responses

I've read the Feathers book, so I know that to create an error response I simply instantiate the appropriate feathers-errors class:
import {BadRequest} from 'feathers-errors';
const errorResponse = new BadRequest(`foo`, `bar`);
However, I'm having difficulty returning that error response to the user. Even when I create an endpoint that does nothing but return an error response ...
class SomeService {
create(data) {
return new BadRequest(`foo`, `bar`);
}
}
it doesn't work: instead of getting an error response, I get no response, and inside the Chrome debugger I can see that the response is pending (until it eventually times out and becomes an ERR_EMPTY_RESPONSE).
I tried reading about Express error handling, and in the examples I saw people used next to wrap the the response. However, next comes from the error handler, and I'm not sure where in my Feathers code I can get that next function.
If anyone could help explain (using next or not) how I can return a complete, not pending, error response, I would greatly appreciate it.
Your services have to return a promise. If your code is not asynchronous you can turn it into a promise with Promise.resolve and Promise.reject:
class SomeService {
create(data) {
return Promise.reject(new BadRequest(`foo`, `bar`));
}
}
Also make sure you registered the Express error handler to get nicely formatted errors:
const errorHandler = require('feathers-errors/handler');
// Last in the chain
app.use(errorHandler);
There is also more information in the error handling chapter.

Grails 2.5.0 controller command object binding after accessing request.JSON in a filter

In a Grails 2.5.0 controller action method, it seems like the properties in the HTTP JSON body will not be used for command object binding if request.JSON has been accessed in a filter.
Why is that? It doesn't make any sense to me.
Is there any way to allow request.JSON to be used in a filter, and also for command object binding?
Yes, this is the default behavior of Grails while it comes to data binding with request body. When you read the request body via request.JSON in your filter then the corresponding input stream will be closed or gets empty. So, now Grails can't further access that request body to bind to the command object.
So, you can either access the request body on your own in the filter or can use it with the command object but can't both.
From Binding The Request Body To Command Objects heading http://grails.github.io/grails-doc/2.5.0/guide/theWebLayer.html#dataBinding:
Note that the body of the request is being parsed to make that work.
Any attempt to read the body of the request after that will fail since
the corresponding input stream will be empty. The controller action
can either use a command object or it can parse the body of the
request on its own (either directly, or by referring to something like
request.JSON), but cannot do both.
So, what are you trying to achieve is not possible directly. But, you can do something different. In your filter, read the incoming request body and store into the params or session (if filter passes the request to controller) and then manually bind the parameter in action:
MyFilters.groovy
class MyFilters {
def filters = {
foo(/* your filter */) {
before = {
// Your checks
Map requestData = request.JSON as Map
session.requestData = requestData
return true
}
}
}
}
Now, in your controller action, instead of doing:
class MyController {
def fooAction(MyCommandObject object) {
}
}
Do something like this:
class MyController {
def fooAction() {
MyCommandObject object = new MyCommandObject(session.requestData)
// Clear from session to clear up the memory
session.requestData = null
}
}
Update: The above solution, I've provided will work well but is not clean. #JoshuaMoore provided a link with a cleaner solution Http Servlet request lose params from POST body after read it once.

Setting Http Status Code and customized status message and returning JSON output using Jersey in RESTful Service

I have implemented a RESTful service using Jersey. I am able to return the desired output in JSON format. But, I also need to set Http Status Code and my customized status message. Status code and status message should not be part of the JSON output.
I tried following links:
JAX/Jersey Custom error code in Response
JAX-RS — How to return JSON and HTTP status code together?
Custom HTTP status response with JAX-RS (Jersey) and #RolesAllowed
but I am able to perform only one of the tasks, either returning JSON or setting HTTP status code and message.
I have code something like below:
import javax.ws.rs.core.Response;
public class MyClass(){
#GET
#Produces( { MediaType.APPLICATION_JSON })
public MyObject retrieveUserDetails()
{
MyObject obj = new MyObject();
//Code for retrieving user details.
obj.add(userDetails);
Response.status(Status.NO_CONTENT).entity("The User does not exist").build();
return obj;
}
}
Can anyone provide solution to this?
the mistakes are :
1. if status is set to NO_content (HTTP204) the norm is to have an entity empty. so entity will be returned as empty to your client. This is not what you want to do in all case, if found return details, if not found return 404.
2.Produces( { MediaType.APPLICATION_JSON }) tells that you will return a json content, and the content of entity is not a json. You will have to return a json. You will see I use jackson as it's part of Jersey.
set a #Path("/user") to set a endpoint path at least at Resource level.
Need to set a path in order to adress your resource (endpoint)
use a bean in order to pass multiple things. I've made an example bean for you.
as improvement caution with HTTP return, use the proper one
404 :not found resource
204 : empty....
take a look at the norm: http://www.wikiwand.com/en/List_of_HTTP_status_codes
Take a look the complete code in Gist: https://gist.github.com/jeorfevre/260067c5b265f65f93b3
Enjoy :)

Send both JSON response and model in Grails

I'm new to Grails and I'm stuck up with a problem. I want to know if there is a way to send both JSON and view and model through "render" in Grails.
I'm using a jQuery Datatable to display data returned from server which is read from JSON returned by the controller. I also need to display error messages on the same view in case of validation failure in form fields. But I'm able to return either only the JSON or model and view using render. I also tried sending the JSON through model itself but it didn't work.
This is my code:-
def hierarchyBreakInstance = new HierarchyBreak(params);
String json = "{\"sEcho\":\"1\",\"iTotalRecords\":0,\"iTotalDisplayRecords\":0,\"aaData\":[]}";
hierarchyBreakInstance.errors.reject(message(code: 'hierarchyBreak.error.division.blank'));
render(view: "hierarchyBreak", model: [hierarchyBreakInstance: hierarchyBreakInstance]);
//render json;
The gsp code:-
<g:hasErrors bean="${hierarchyBreakInstance}">
<div class="errorMessage" role="alert">
<g:eachError bean="${hierarchyBreakInstance}" var="error">
<g:if test="${error in org.springframework.validation.FieldError}" > data-field-id="${error.field}"</g:if>
<g:message error="${error}"/>
</g:eachError>
</div>
</g:hasErrors>
Could you please let me know if there is a way to do this. Thanks!
You can use like this.
def hierarchyBreakInstance = new HierarchyBreak(params);
String json = "{\"sEcho\":\"1\",\"iTotalRecords\":0,\"iTotalDisplayRecords\":0,\"aaData\":[]}";
hierarchyBreakInstance.errors.reject(message(code: 'hierarchyBreak.error.division.blank'));
render(view: "hierarchyBreak", model: [hierarchyBreakInstance: hierarchyBreakInstance,json:json]);
//render json;
Assuming that you are doing a request with some parameters, and need to return if was succesfull or not, and the data to fill the table with ajax.
I will do on that way, use the statuses of the HTTP to mark if it was a problem with the validation(normally we return 400 Bad Request and the message)
Example :
return ErrorSender.sendBadRequest("error validating field $field with value $value")
And the errorsender has a sendBadRequest method
[response: ['message': message, error: "bad_request", status: 400, cause: []], status: 400]
If the request was OK, you only need to respond the data with something like
return [response: results, status: 200]
In the client side you have to have one function if the request was OK to parse result, and one function if request have some validated data problem, database problem or whatever that caused that the request didn´t return a 200(in the example),there are more status codes, you can check on
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
PD: Initial validation should be done on client side.