Trying to add User in Laravel using Angular but it shows me an error - json

I'm trying to use the post method to pass the user to Laravel using a form in HTML so I can store the user in the UserController into the database. I get an CSRF Token mismatch error.
I have used this Method to store the user:
addUser(user: User):Observable<User>{
return this.http.post<User>(this.apiURL+'/addUser',user, httpOptions);
}
When I console.log the user it works fine. It shows me all attributes when I klick on submit.
I have use this Route in Laravel to store the user:
Route::post('/addUser','UserController#create');
In the Controllermethod I used this code:
public function create(Request $request)
{
$data2 = $request->json()->all();
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}

Laravel, by default, has VerifyCsrfToken middleware enabled for all routes. This is for security (to avoid cross site attacks) and checks for a CSRF token for all requests. But you can set middlewares for route groups such as web, api',console`.
Try to move VerifyCsrfToken middleware from $middleware variable to web group in $middlewareGroups variable in Http/Kernel.php. By doing this, you only enable this middleware for web routes.
Hope this helps.

Related

return errors while using API routes in Laravel 8

I'm building a small application to store contacts in the database, I've finished the GET/POST routes, and worked fine, now I'm on the API routes (in order to use AJAX calls). I can store the information if all fields are present in the POST request, nonetheless, If I want to send messages back to the call (to send feedback about why the contact hasn't been stored) the response is sending me to the main route www.myapp.com (with no messages) and I want to send a json back with the "reason".
At this moment I only validate if the 'nombre', 'correo', 'telefono' have information with standard Laravel's request validate method.
This is my LeadController
public function storeApi(Request $request)
{
$request -> validate([
'nombre' => 'required',
'correo' => 'required' ,
'telefono' => 'required'
]);
if(Lead::create($request->all())){
$result[] = ['saved' => true];
}else{
$result[] = ['saved' => false,
'reason' => 'Some data is missing'];
return response()-> json($result);
};
return response()-> json($result);
}
When the record is stored, it does send back the Json {'saved' : true} but when fails It just sends you back to the '/' Route: www.myapp.com
How can I send the messages back to the POST call?
It is redirecting back to "/" because $request->validate() method throws \Illuminate\Validation\ValidationException exception..
There are try ways to handle this request.
Put try catch block around your validate code
Or Handle this expection in app\Exception\Handler.php, and return the response in JSON format.
After some further reading I just change the way the information is validated using the Validator Class:
public function storeApi(Request $request)
{
$validator = \Validator::make($request->all(), ['nombre' => 'required', 'correo' => 'required', 'telefono' => 'required']);
if($validator->fails()){
return response()->json($validator->errors(), 422);
}else {
//ready to store
}
}
This way I don't let the ValidationException exception occurs before sending the feedback to the call.

Laravel 5.8 validation return to home after it fails while using Passport

I have a store() method.
public function create(StorePost $request)
{
$post = Post::create([
'title' => $request->title,
'description' => $request->description,
]);
return response()->json([
'post' => $post
], 201);
}
In my StorePost class, I validated the request.
public function rules()
{
return [
'title' => 'required|string|max:255',
'description' => 'required',
];
}
When I tested it with Postman with wrong entries, for example, if I fill 'description' with a null value, it returns to the home page without any response or error. How can I retrieve the validation errors?
I solved it just by adding 'Accept': 'application/json' in my request's header.
This happens because Laravel Form Request works both for API and non-API requests.
On requests made by a form, it will redirect back (to the original form url or home if not sent from a form) with an error bag on $errors variable available to the view.
On requests made by ajax (usually on APIs) usually have the header Accept: application/json, so Laravel automatically knows that you want the validation error bag as json on the response body instead of a redirect that makes no sense for an API.
Hope this can clarify thing to you.

Yii2 Make endpoint accessible through web and rest api

A customer has requested to have the exact same endpoints available through web interface as well as through REST API.
The same endpoint should be visible using web browser only when being logged in. When accessing it via REST API, a valid access token must be submitted.
The rule for this specific endpoint is defined as follows:
[
'class' => 'yii\rest\UrlRule',
'controller' => 'site',
'pluralize' => false,
'extraPatterns' => [
'POST upload-raw-data' => 'uploadRawData'
],
]
Now, when I try to access this endpoint, I've got these results:
Browser: no problem
Postman / POST: 404 error
Postman / GET: no problem
When trying the same with enableStrictParsing enabled, I've got 404 errors all around.
If I need to provide other parts of the code, I'll happily provide them.
I think I found the solution for my issue. The problem seems to have been the CSRF validation.
By disabling it for this specific action in beforeAction(), the POST call behaves as intended.
public function beforeAction($action) {
if ($action->id == 'upload-raw-data')
Yii::$app->controller->enableCsrfValidation = false;
return parent::beforeAction($action);
}
source: https://gist.github.com/guerreiro/9e9cb3154b9047f5d2a0

Laravel 5.4 Passport Implicit Grant Tokens returns a url with the access token, How to return with json?

After adding the Passport::enableImplicitGrant(); in AuthServiceProvider.php then testing with the route
Route::get('/redirect', function () {
$query = http_build_query([
'client_id' => 3,
'redirect_uri' => 'http://consumer.dev/callback',
'response_type' => 'token',
'scope' => '',
]);
return redirect('http://passport.dev/oauth/authorize?'.$query);
});
the result is appended in the https://consumer.dev/callback/ url like this
https://consumer.dev/callback/#access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImI1YTBhMTllYTEwMTI0ZTc2MGE5MjJkOGUxYTg1OTQyODc1ZGJjNzlmMmI1YTVlZTVmNzJhNDkzZjgxZmFhNGNhZWFkYzIyYmNkNjRlNzQ4In0.eyJhdWQiOiIyIiwianRpIjoiYjVhMGExOWVhMTAxMjRlNzYwYTkyMmQ4ZTFhODU5NDI4NzVkYmM3OWYyYjVhNWVlNWY3MmE0OTNmODFmYWE0Y2FlYWRjMjJiY2Q2NGU3NDgiLCJpYXQiOjE0ODk0NjA0MTksIm5iZiI6MTQ4OTQ2MDQxOSwiZXhwIjoxNTIwOTk2NDE5LCJzdWIiOiIxIiwic2NvcGVzIjpbXX0.EC3ZFELGBj683SZczlGfLOLiH72Sjj34QnwuBeSWsXKs3A9Btx_SbyU6NuK_-WCdeOqS_B_BsZtwtpbqGBVpqYGUBXNwah4WaRg-UB2ojxO0qFT11Mpyfbz0qtK-QZumG6PvkSNeHicE2EgnPo-btjDgYqc4927Z9npIeLTv4URqlu7dDCN2onukTGNES1aq5ysJbiAzQMk5X64DxQOV69pOBDcn5WtRFG5pABBN1D01HSUZ878g-SAkLL28LoonA90f0jsg9Bjgw7rAau1Eb7SIF3APW5o3r4H5LCcPDl_-vt0LDR317Ccv6wNk6284XvDvDnERtqsb3aG6sTLK0MuqvBTy8S-NCUPt8xk8lKf2aLPAy2HqAdhCXyRRtx82mhtC4NVNxVKWZu53yqMk-78i5JSvGfXfrdVR6lnXKy4_l7UVhwhqUDBjN9Qaj-2bbHsIicHWKZT4JaXBr4bsOXHSwrdqrYiICwZGik1FEMSVR_13MFp8tlP8C_A4rbiDHjByZQEg4128XfizcE-BzGKV5FNRgGQPwB41Gjpgpdgsz3p-4ybaYiniVGio9-9JO36PlhVO3zRbe3p5PBPy-DYaByODC3czXkgUagBgZ4_3GejThSNCluLY3CVw4NrFdgbkBOq2MtdwgLW5JlBiD3NqN0LTQb63t8S5QGaLEFg&token_type=bearer&expires_in=31535999
how to return access token to a json not appended in the url or how to properly used the implicit grant in laravel passport and returning the token to a json format.?
Do you mean
return response()->json('http://passport.dev/oauth/authorize?'.$query);
By using Passport::enableImplicitGrant() and including the response_type => 'token', you are telling oAuth explicitly to use ImplicitGrant flow which as per OAuth specification will return the access_token in the fragmented url (after the # part). This is the correct behavior if you like to have the response in JSON you may consider using the other oAuth grant_types.
Please see the link below for further explanation on implicit grant flow
https://www.rfc-editor.org/rfc/rfc6749#section-4.2
https://oauth.net/2/grant-types/implicit/

getting csrf tokens for json post requests to a rails app

I have been playing around with using rest-client to access a rails app I have written. I've written a quick script to log in and make a post request. Everything is working but I did have to work round the fact that no authenticity_token is served if you make a request for a form in json. I had to make a regular html request in other get the authenticity_token and then included this in the json I submitted as part of my post request. Basically I have a quick an dirty script like the one below
private_resource = RestClient::Resource.new( 'https://mysite.com')
params = {:user => {:email => 'user#mysite.com', :password => 'please'}}
#log in
login_response = private_resource['users/sign_in'].post(params, :content_type => :json, :accept => :json)
#get cookie
cookie = login_response.cookies
#get json
json_response = private_resource['products/new'].get(:content_type => :json, :accept => :json, :cookies => cookie)
#another request that returns html form with authenticity token
response_with_token = private_resource['products/new'].get( :cookies => cookie)
#extract token
token = Nokogiri::XML(response_with_token).css('input[name=authenticity_token]').first.attr('value')
#update cookie
cookie = response_with_token.cookies
#populate form and insert token
form = JSON.parse(json_response)
form['name'] = "my product"
form['authenticity_token'] = token
#submit the request
private_resource['products'].post(form.to_json, {:cookies => cookie, :content_type => :json, :accept => :json})
There is the option to turn off CSRF protection for json requests but I would rather not do that. I could go the mechanize route or something similar and then I wouldn't worry about json requests with CSRF but I just wanted to play around with doing this stuff with rest-client
I guess I'm just curious to know if there is a reason why no authenticity_token is served for json requests and I'm also wondering if there is a better way of solving the token problem than the pretty hacky approach I've taken here
Put the below code into your application controller :
def verified_request?
if request.content_type == "application/json"
true
else
super()
end
end
And call this method using before_filter .
For more details check :
http://blog.technopathllc.com/2011/09/rails-31-csrf-token-authenticity-for.html
And check this issue in rails : https://github.com/rails/rails/issues/3041
In your app/views/products/new.json.jbuilder, add this:
json.authenticity_token form_authenticity_token
This will insert a key "authenticity_token" with value being the token, so in your json_response you get the token as well. Idea from this answer.