Cross-Origin Request while using a post request from Ionic to Laravel - laravel

I'm trying to send a post request from my frontend ( Ionic ) to my backend Laravel ! it return that Cors error. I've already made the Cors class in Laravel and added it the routeMiddleware, I have also tried the solution made by barryvdh and it's also not working. when I try the request using the get method it works but it's not the same case while using post method.
here my handle method in Cors class in laravel :
public function handle($request, Closure $next)
{
header("Access-Control-Allow-Origin: *");
// ALLOW OPTIONS METHOD
$headers = [
'Access-Control-Allow-Origin'=> '*',
'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Headers'=> 'Content-Type, X-Auth-Token, Origin'
];
if($request->getMethod() == "OPTIONS") {
// The client-side application can set only headers allowed in Access-Control-Allow-Headers
return Response::make('OK', 200, $headers);
}
$response = $next($request);
foreach($headers as $key => $value)
$response->header($key, $value);
return $response;
}
middleware array in Kernel.php
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\Cors::class,
];
api part of the middlewareGroups array in Kernel.php
'api' => [
'throttle:60,1',
'bindings',
\App\Http\Middleware\Cors::class,
]
routeMiddleware array in Kernel.php
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'jwt.auth' => Tymon\JWTAuth\Http\Middleware\Authenticate::class,
'jwt.refresh' => Tymon\JWTAuth\Http\Middleware\RefreshToken::class,
'cors' => \App\Http\Middleware\Cors::class,
];
The route I'm trying to call
Route::post('auth/login', 'ApiController#login');
Here the code I'm executing in ionic
login(emaill: string, passwordd: string) {
return this.http.post<any>(
`${environment.laravelBackend}/auth/login`,
{ email: emaill, password: passwordd}
);
}
Anyone knows how I can make this work ?
Thanks in advance

there may be 2 solutions try both if first or second does not work.
1) Sometime, it not works due to the developer's composer version where the API is made, and the machine where you have setup the environment's composer version is different. check it. and if possible, send your and the machine where api is developed's composer version.
2) Add CORS in .htaccess File like this
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS"
Header set Access-Control-Allow-Credentials "true"

Related

Access to XMLHttpRequest at 'https://......login' from origin 'https://.....r.in' has been blocked by CORS policy

I have hosted laravel and angular application on server it was working before but now it is throwing below error :
Access to XMLHttpRequest at 'https://......login' from origin
'https://.....r.in' has been blocked by CORS policy: Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
I have created CORS middleware :
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class CORS
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
header('Acess-Control-Allow-Origin: *');
header('Acess-Control-Allow-Origin: Content-type, X-Auth-Token, Authorization, Origin');
return $next($request);
}
}
api route file:
Route::group(['middleware' => 'api','cors','prefix' => 'auth'], function ($router) {
Route::post('/login', [AuthController::class, 'login']);
Route::post('/register', [AuthController::class, 'register']);
Route::post('/logout', [AuthController::class, 'logout']);
Route::get('/user-profile', [AuthController::class, 'userProfile']);
});
Kernel.php
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'guest' => \App\Http\Middleware\CORS::class,
];
}
Any solution is highly appreciated, Thanks
the error is in the browser, so you need to have those headers on the response. For this, you need to have middleware for the response, see https://laravel.com/docs/8.x/middleware#middleware-and-responses
$response = $next($request);
// add headers to response here
return $response;
Additional info:
You need to edit your CORS middleware.
it will look like this:
$response = $next($request);
if ($request->getMethod() !== 'OPTIONS') {
return $response;
}
$response->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Headers', 'Content-type, X-Auth-Token, Authorization, Origin');
return $response;
You made a few typos:
Acess should be Access
and in the Kernel.php you have
'guest' => \App\Http\Middleware\CORS::class,
But I think it should be
'cors' => \App\Http\Middleware\CORS::class,
because you use cors name in your routes.
Updated again:
The second header should be Access-Control-Allow-Headers instead of Access-Control-Allow-Origin
It might throw another error about allowed methods(because it said preflight request) so you will need to fix it by adding Access-Control-Allow-Methodssee https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
Regarding the error:
getting Access to XMLHttpRequest at 'https://beta-XXX/api/auth/login' from origin 'https://XXXXX.in' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response
It says that the preflight request (in that case, it is OPTIONS, not GET or POST) doesn't allow Content-Type. This is because it is not applied to this kind of method. In that case, there should be a new route under middleware cors like
Route::options('/login', ...);
But since you will need it in other places as well, then it is better to customize the CORS middleware for preflight requests through the entire application by adding your Cors middleware into the $middleware array (then it will run for every request). Please try/test that if needed. Then it might be that it is needed only for OPTIONS requests, if it is true then I'd add(I've modified it in the above snippet as well)
if ($request->getMethod() !== 'OPTIONS') {
return $response;
}
WARNING/NOTICE:
if you make it to work, the next step would be to make sure that you specify what origins are allowed in production. Instead of *, you should have a list of domains that are allowed to use it (or even better you can respond with * only for allowed hosts).

How to fix ERR_TOO_MANY_REDIRECTS using Laravel Middleware?

I am using Laravel 8 and when i redirect a route from middleware i am facing issue
ERR_TOO_MANY_REDIRECTS. I am verifying user with firebase otp and set cookie if otp verify then i want to redirect register page if user not exist in db. I have create middleware and check if cookie set then redirect to register route.
public function handle(Request $request, Closure $next)
{
if (Cookie::get('otpVerified')){
return redirect()->route('register');
}
return $next($request);
}
after that i am facing this issue
enter image description here
my route file is
Route::get('/register', [RegisterController::class, 'register'])->name('register_user');
Auth::routes();
Route::group(['middleware' => 'otpVerify'], function (){
Route::get('/404', [\App\Http\Controllers\ErrorController::class, 'notFound'])->name('404');
Route::get('/', [\App\Http\Controllers\Dashboard\DashboardController::class, 'index'])->name('dashboard');
});
How can i fix it. My kernel file is
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
and
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'otpVerify' => \App\Http\Middleware\OTPVarification::class,
];
In this section, you must exclude the register root
public function handle(Request $request, Closure $next)
{
if (Cookie::get('otpVerified') && $request->route()->getActionName() !== 'YourRegisterAction'){
return redirect()->route('register');
}
return $next($request);
}

Permission Middleware with Laravel 6.6 working on all routes

Hi I am working on laravel project , I have to check about user's permission when he trying to access one page , my problem is after I created Permission middle ware , and add it in the kernel.php , it checking about permissions for all route even I did not call it in any route .
I don't want to apply this middleware on all route , just some of it .
this is my permission middleware's code
namespace App\Http\Middleware;
use Closure;
use Session;
use App\Rules;
use Illuminate\Support\Facades\Route;
use URL;
class Permissions
{
public function handle($request, Closure $next) {
$rolename=Session::get('rule_name') ;
$route = $request->path();
$hasPermission = Rules::where('rule_name', 'superadmin')->where('allowed_pages', 'like', '%' . $route . '%') ->first();
if (empty($hasPermission)) {
echo 'Unauthorized.Go Back';
die();
}
}
}
}
and this is my route file
Route::resource('Login', 'LoginController')->name('index','Login');
Route::resource('Backup', 'BackupController')->name('index','Backup');
as you see I did not apply the middleware on these tow route , but the middleware is working with these tow routes
this is my kernel code
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
'Permissions' => \App\Http\Middleware\Permissions::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
I want to run this middleware only by route like this
Route::group(['middleware' => 'permissions'], function () {
Route::resource('Backup', 'BackupController')->name('index','Backup');
}
thank you for advance
best regards
You added your middleware to the middelwareGroup web, wich applies the middleware to every request comming in.
You need to add your middleware to the routes middleware array: docs
// Within App\Http\Kernel Class...
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
...
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
// your own middlewares:
'Permissions' => \App\Http\Middleware\Permissions::class,
];
You can than apply the middleware to specific routes:
Route::resource('Login', 'LoginController')->middleware('Permissions')->name('index','Login');
you added inside web which is default middleware by laravel that's why it's applied in all route.
to register a middleware you need to add in protected $routeMiddleware = [ ] array
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
//custom middlewares:
'Permissions' => \App\Http\Middleware\Permissions::class,
];
then only
Route::group(['middleware' => 'permissions'], function () {
Route::resource('Backup', 'BackupController')->name('index','Backup');
}
it will work

Laravel bearer token authentication

I want to make authentication for API requests coming from mobile users.
I followed this
and made api_key column inside users table.
I also created middleware:
public function handle($request, Closure $next)
{
$token = $request->bearerToken();
return $next($token);
}
What I want is to get bearer token from header and check it against user table.
How to achieve this?
Append the auth:api middleware to any route or group of routes and the Bearer token will be checked automatically for you without a custom middleware
Route::get('url', 'controller#method')->middleware('auth:api');
But to answer the question, here's what you can do (still not recommended but works)
<?php
namespace App\Http\Middleware;
use Closure;
class ApiAuthentication
{
public function handle($request, Closure $next)
{
$token = $request->bearerToken();
$user = \App\User::where('api_token', $token)->first();
if ($user) {
auth()->login($user);
return $next($request);
}
return response([
'message' => 'Unauthenticated'
], 403);
}
}
Register the middleware in App\Http\Kernel
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
// Here for example
'custom_auth' => \App\Http\Middleware\ApiAuthentication::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
And protect a route with that middleware name
Route::get('/', function () {
// Return authenticated user model object serialized to json
return auth()->user();
})->middleware('custom_auth');
Result
I would recommend laravel/passport as it is much secure and easier.
Click Here.

Session cookie is removed after redirect method (Laravel 5.4)

I am trying to use an OpenID Connect library in PHP, I have downloaded and tested this one: https://github.com/jumbojett/OpenID-Connect-PHP
It worked perfectly, but then I started a Laravel 5.4 project and added the library to it. My idea is to use a middleware to redirect the user to the library and authenticate the user when the 'admin' page is requested.
But when the program reaches a 'redirect' method the session is lost, which didn't happen when I wasn't using Laravel.
This is the web.php file
Route::group(['middlware' => 'web', 'auth'], function () {
Route::get('admin', 'KeycloakController#auth');
});
This is the kernel.php file
protected $middlewareGroups = [
'web' => [
\MiddlewareTest\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\MiddlewareTest\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
'auth' => [
'keycloak' => \MiddlewareTest\Http\Middleware\Keycloak::class,
],
];
When the controller is reached, I call this method from another class
private function requestAuthorization() {
$auth_endpoint = $this->getProviderConfigValue("authorization_endpoint");
$response_type = "code";
// Generate and store a nonce in the session
// The nonce is an arbitrary value
$nonce = $this->generateRandString();
Session::put('openid_connect_nonce', $nonce);
// State essentially acts as a session key for OIDC
$state = $this->generateRandString();
Session::put('openid_connect_state', $state);
Session::save();
\Log::info(session('openid_connect_state'));
$auth_params = array_merge($this->authParams, array(
'response_type' => $response_type,
'redirect_uri' => $this->getRedirectURL(),
'client_id' => $this->clientID,
'nonce' => $nonce,
'state' => $state,
'scope' => 'openid'
));
// If the client has been registered with additional scopes
if (sizeof($this->scopes) > 0) {
$auth_params = array_merge($auth_params, array('scope' => implode(' ', $this->scopes)));
}
$auth_endpoint .= '?' . http_build_query($auth_params, null, '&');
$this->redirect($auth_endpoint);
}
But, when the browser goes to that URL in the 'redirect' method, the session is lost - I don't know why.
Please help me to understand why is this happening.
Thanks in advance.

Resources