ionic laravel XMLHttpRequest cannot load - angularjs

i am new to this and i am trying to login and get a token so the ionic and laravel can communicate. I am using satellizer and jwt on laravel. on post man i get the token back:
this is what i am getting loging in from ionic:
[enter image description here][2]
the error says:
XMLHttpRequest cannot load http://localhost:8000/api/authenticate. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access.
and yeah, on my laravel side, i have included
header("Access-Control-Allow-Origin: *");
what am i missing here, thank you

There are many factors to why this happens. the error may happen because you have no access headers and the browsers gets this and blocks your requests.
It also happens when you your server experiences internal errors like 500,403,401 etc. you may have added headers to the requests life cycle(like in the middleware to filter all api requests) in your laravel app but sometimes an error 500 or even an echo or dd() interrupts the whole request life cycle and returns the errors WHICH the browser can't interpret through an ajax call and therefore it loses the headers you implicitly added thus the browser goes back to the preflight request error..
The only solution I suggest is proper error handling in your code and returning errors in a response and return it in json format.
public function someController extends Controller{
public function Foo(Request $request){
$input_bag = [
'some input' => first_$input,
'another important input' => $second_input,
];
$i = 0;
foreach ($input_bag as $key => $value) {
$value = trim($value);
if (empty($value)) {
$error_bag[$i] = "$key empty";
$i++;
} else {
//
}
}
//filter of false or null values
if (array_filter($error_bag)) {
return response()->json($error_bag, 400);
}
}
this returns a json response of the errors while running the code. and good use of try catches and returning the appropriate responses could make your debugging life easy.

Related

404 Not Found error in preflight OPTIONS when executing a PUT method in CakePHP API with axios in React App

So, we have an API with CakePHP 3.7. We are using resources to generate CRUD methods. The API is hosted in a server with apache2 and is accessed through a manager app using React (this app is a microservice). The manager makes the calls through axios and is correctly managing the GET, POST and HEAD requests (simple CORS requests) but we're having problems when it comes to more complex requests such as PUT or DELETE.
When executing PUT or DELETE requests it makes a preflight OPTIONS request and it returns a 404 Not Found error. And some messages in console related with CORS which are:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSPreflightDidNotSucceed?utm_source=devtools&utm_medium=firefox-cors-errors&utm_campaign=default
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSDidNotSucceed?utm_source=devtools&utm_medium=firefox-cors-errors&utm_campaign=default
We already tried several fixes, such as using CakePHP CORS plugin, adding CORS Headers in the response in the beforeRender and beforeFilter methods of AppController and also adding CORS headers in the apache, none of this seams to be working.
private function setCorsHeaders() {
$this->response->cors($this->request)
->allowOrigin(['*'])
->allowMethods(['*'])
->exposeHeaders(['X-Total-Pages'])
->maxAge(800)
->build();
}
public function beforeRender(Event $event)
{
$this->setCorsHeaders();
}
public function beforeFilter(Event $event)
{
if($this->request->is('options')) {
$this->setCorsHeaders();
return $this->response;
}
}
Header set Access-Control-Expose-Headers "X-Total-Pages"
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS"
The expected behaviour is that the PUT and DELETE methods are executed properly (the preflight OPTIONS should pass successfully). Any help is apreciated.
In CakePHP >=3.4, Http\Response objects are treated as immutable by many methods. The method chain called on $this->request->cors() uses the CorsBuilder class to queue the desired headers on an immutable response which is returned when calling build().
Try assigning the return from CorsBuilder::build() with the queued headers to $this->response.
private function setCorsHeaders() {
$this->response = $this->response->cors($this->request)
->allowOrigin(['*'])
->allowMethods(['*'])
->exposeHeaders(['X-Total-Pages'])
->maxAge(800)
->build();
}

Laravel 5.4 / Angular possible mishandled rejection due to cross origin request blocked

I am currently building an application using token based authentication with Angular and Laravel. I initially set things up just to test the API by creating a BookController . At first I was getting a Cross Origin Request Block error when I tried to call this data from Angular. However I managed to resolve this by adding the headers to my routes/web.php file. Here is the whole file. NB: After adding these headers I was succesfully able to use the API even from another domain
<?php
header('Access-Control-Allow-Origin: *');
header( 'Access-Control-Allow-Headers: Authorization, Content-Type' );
//Route::get('/', 'BookController#show');
//Route::resource('book/create', 'BookController#create');
Auth::routes();
Route::get('/', 'HomeController#index');
Route::resource('book', 'BookController');
Route::resource('authenticate', 'AuthenticateController', ['only' => ['index']]);
Route::post('authenticate', 'AuthenticateController#authenticate');
However I am currently following this tutorial to set up token based authentication. https://scotch.io/tutorials/token-based-authentication-for-angularjs-and-laravel-apps
To summarise , my issue is when I submit the form containing username and password I am getting the following errors. Below I will try elaborate a bit more but it is quite difficult as there is alot to it.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://www.example.local/authenticate/.
(Reason: CORS header 'Access-Control-Allow-Origin' missing).
And
Possibly unhandled rejection:
{"data":null,"status":-1,"config":{"method":"POST","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"http://www.example.local/authenticate/","data":{"email":"dasdas#Dasa.com","password":"fsdfd"},"withCredentials":false,"headers":{"Accept":"application/json,
text/plain,
/","Content-Type":"application/json;charset=utf-8"}},"statusText":""}
I am using Angular UI Router V 0.4.2 and satellizer. My Angular version is 1.6.2 It using a different domain than the API. Much like the working example above.
On the laravel side I also followed this tutorial to add middleware to attempt to resolve this but no luck.
http://en.vedovelli.com.br/2015/web-development/Laravel-5-1-enable-CORS/
I will also include my AuthenticateController.php file..
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
use App\User;
class AuthenticateController extends Controller
{
public function __construct()
{
// Apply the jwt.auth middleware to all methods in this controller
// except for the authenticate method. We don't want to prevent
// the user from retrieving their token if they don't already have it
$this->middleware('jwt.auth', ['except' => ['authenticate']]);
$this->middleware('cors');
}
public function index()
{
// Retrieve all the users in the database and return them
$users = User::all();
return $users;
}
public function authenticate(Request $request)
{
$credentials = $request->only('email', 'password');
try {
// verify the credentials and create a token for the user
if (! $token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'invalid_credentials'], 401);
}
} catch (JWTException $e) {
// something went wrong
return response()->json(['error' => 'could_not_create_token'], 500);
}
// if no errors are encountered we can return a JWT
return response()->json(compact('token'));
}
}
My issue is I do not even know if the "possibly unhandled rejection" is related to the "Cross-Origin Request Blocked" error. But I have to assume it is.
Can you recognise anything from my routes files that may be allowing one and not another?
EDIT:
I have noticed the difference between one request and another is that one is a GET request while another is an OPTIONS request. This may be the cause.
I have since added Header set Access-Control-Allow-Origin "*" to both the virtual hosts config file in Apache and to a .htaccess file in the root of the Laravel project. Still no change.
I am wondering is this related something in Angular
Your server code needs to handle that OPTIONS request by sending a headers-only response to it that includes the Access-Control-Allow-Methods: GET, POST, PUT, DELETE header and Access-Control-Allow-Headers: Authorization, Content-Type header.
Or you can just try using https://github.com/barryvdh/laravel-cors which makes all this easier.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests has general info you might want to read up on.

CakePHP: Redirect to login from custom component

In a custom component I am making API calls. If the API call returns 403 I want to logout the user and redirect to the login. With the following code I get a response object without knowing if the response is a redirect or if the response is containing the data of the request. Besides get I have also other methods implemented in the Component so that I have at the end over 50 times a call to the RestAPIComponent.
Calling the RestAPIComponent
public function view($id)
{
$resource = $this->__getSingularResourceName();
$$resource = $this->RestApi->get($id)->json;
$this->set(compact($resource));
}
RestAPIComponent
public function get($id = null, array $query = [], $action = null)
{
$path = (is_null($id) === false) ? $id : '';
$response = $this->_http->get($path . '/' . $action, $query, $this->_getAuthHeader());
return $this->_handleResponse($response);
}
private function _handleResponse(Response $response)
{
if ($response->statusCode() == 403) {
$this->Cookie->delete(TOKEN);
$this->Cookie->delete(USER);
$controller = $this->_registry->getController();
return $controller->redirect($controller->Auth->logout());
} else {
return $response;
}
}
There may be following reasons behind it, getting the 403 error using auth component --
1.It is possible to get a 403 via code. Check this out from the CakePHP docs (http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#handling-unauthenticated-requests): If authenticator returns null, AuthComponent redirects user to login action. If it’s an ajax request and AuthComponent::$ajaxLogin is specified that element is rendered else a 403 http status code is returned.
2.Multiple Ajax calls shouldn't be the causing factor of a 403 error.
3.The standard routing is handled by CakePHP itself. If you need some different routing, you should configure this in routes.php. I would say using .htaccess is only for a really extreme routing need and should be a last resort.
4.Yes that could be a cause, since you would no longer be logged in, thus get Auth 403s
For more detail -- you could visit the link Common reasons behind 403 errors

Cross-Origin Request Blocked - Laravel

i have try to access(get request) my laravel api from ionic(angularjs) app.
but it keep getting bellow error.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://128.xxx.xxx.xx/mobi/check/?username=achchu&apikey=1N7GyYRfq8bQnrFCCGgL
please help me to fix this
This response is based on the fact that it appears you have control of serve-side code.
Have you added CORS support to the response? If you have not done so it could be like this.
You could add a handler thus:
Route::head("/<path to resource>", function () {
$r = Response::make("hello");
//Access-Control-Allow-Origin: http://api.bob.com
// Access-Control-Allow-Credentials: true
$r->header("Access-Control-Allow-Origin", "<*|client request domain>")
->("Access-Control-Allow-Credentials", "true")
->("Access-Control-Request-Method", "GET");
});
Perhaps you could set this headers on the response you are sending itself, I'm not sure. If that is possible and you might use this sort of thing on several routes it's better you prepare it as a filter. You can read more on CORS at http://www.html5rocks.com/en/tutorials/cors/ .
If what you want to send is json data think about serving your response to support jsonp. You could do something like:
$normalData = Model::all();
// if the client made a jsonp style request
if (Input::has("callback")) {
$data = "<script>" . Input::get("callback") . "(" . json_encode($normalData) . ")";
return Response::make($data)->header("Content-Type", "appplication/javascript");
}else {
//if not then return normally
return Response::json($normalData);
}
You are trying to access api from one domain to a different domain.
There are many ways to overcome this issue,but since it is a get Request,use **jsonp*.
Try something like this
var url = ' http://128.xxx.xxx.xx/mobi/check/?username=achchu&apikey=1N7GyYRfq8bQnrFCCGgL&callback=JSON_CALLBACK';
$http.jsonp(url)
.success(function(data) {
});

303 redirection not working with Angular HTTP POST

I am calling an authentication service where I do a $http.post which returns a 303 resonse, redirecting to a get call returning the response.
When I make the post call using Postman, I get the desired response but when I do an angular $http.post call, it returns me a 401 error (which is user not authorized)
Am I missing something while making the angular call? The backend service seems to work fine as it works fine on Postman.
This is how the $http call looks:
$http.post(url, userData).success(function(data, status) {
//handle success
}.error(function(data, status) {
//handle error
});
The url and the user data is constructed absolutely fine in this case.
The reason that you get a GET call is that the browser handle the 303 response before the angular can reach that. And the handling sequence is first go to the browser and then go to the angular framework.
So briefly what happens is : you make call to the server --> the server return the 303 response -> your browser handle the 303 and make a request to some url (should be 'location' in the response header) --> the server receive the request and return the 401 authorized response --> again the browser receive the 401 response first but this time the browser redirect the response to the angular --> at last you can receive the data and status inside the error().
The solution for this could be switching to other response status code like 2xx, and you can get the location from the body. Then you can do the redirection manually. If you HAVE to use 303 or other 3xx as the response code I don't think there's any effective solution at this moment because you can't do much to the browser. As far as I know there might be a solution at browser level but don't know when that will happen.
Hope this can help anyone has the similar issue like this although it has been nearly one year since this issue raised.
Some other ref: https://groups.google.com/forum/#!topic/angular/GKkdipdMbdo
There's similar solution you can see from the link above.
I faced this issue and I found a redirect url in error object after lots of hours struggle.
loginWithLinkedIn() {
let data = {
// some kind of information here
}
return this.http.get(`https://www.someurl.com/oauth/v2/authorization`).subscribe(res => {
console.log(res)
}, err => {
console.log(err.url) // here is the redirect url
window.location.href = err.url
})
}
Note: when you make a request and you get 303 response which is considered as error, that's why we think we are getting error but error contains useful info.

Resources