Laravel CORS variables - php

I wanted to set up a dynamic CORS middleware which would check on the fly if the subdomain I am using is the valid subdomain for my server. I have tested the logic behind it and it works, but when providing a variable to the header, it seems as if something isn't right?
Here is the code:
public function handle($request, Closure $next)
{
$originalDomain = config('session.domain');
$parsedUrl = parse_url(request()->url());
$splitDomain = explode('.', $parsedUrl['host'], 2);
$subdomain = $splitDomain[0];
$domain = $splitDomain[1];
$subdomainValid = $parsedUrl['host'] != $originalDomain && $originalDomain == $domain;
if(!$subdomainValid)
return $next($request);
$allowedUrl = $parsedUrl['scheme'] . '://' . $subdomain . '.' . config('session.domain_without_dot');
return $next($request)
->header('Access-Control-Allow-Origin', $allowedUrl)
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
}
I am getting the error that No 'Access-Control-Allow-Origin' header is present on the requested resource, but if I dump the variable I got, and paste it in, it works just fine.

I have resolved the issue by changing
$parsedUrl = parse_url(request()->url());
to
$parsedUrl = parse_url($_SERVER['HTTP_ORIGIN']);
Explanation
Since this middleware is put on the server, when request goes through the middleware, the request()->url() is actually the value of the server URL, not of the subdomain requesting it. With this change I am fetching an URL of the subdomain which requested the server resource.

Related

Angular9 http post CORS issue

I am new to Angular9, I have tried to save data by calling a php API from my angular9 application, but geting the following error.
I have test this service from postman, which is working fine and save data successfully
Access to XMLHttpRequest at 'http://127.0.0.1/angularCRUDservices/user/saveEmployee' from origin 'http://localhost:4200' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
**Please Note:** get method is working fine to fetch data,
my Angular service:
reqHeader = new HttpHeaders(
{
'Content-Type': 'application/json',
'No-Auth':'True',
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Header':'Access-Control-Allow-Origin,X-Requested-With,Content-Type,Access',
'Access-Control-Allow-Methods':'GET,POST,DELETE,PATCH,PUT,OPTIONS'
}
);
constructor(private httpClient:HttpClient){}
saveEmployee(formData:Employee){
console.log(formData);
this.httpClient.post<{response:any,success:boolean}>("http://127.0.0.1/angularCRUDservices/user/saveEmployee",formData,{
headers : this.reqHeader
})
.subscribe((response)=>{
console.log(response);
})
}
php service code:
setting headers in constructor:
public function __construct()
{
parent::__construct();
$this->load->helper('url');
$this->load->model('user_model','usr');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Header: Access-Control-Allow-Origin,X-Requested-With,Content-Type,Access');
header("Access-Control-Allow-Methods: GET,POST,DELETE,PATCH,PUT,OPTIONS");
header('Content-Type: application/json, charset=utf-8');
}
service:
public function saveEmployee()
{
$input = array();
try
{
$UserID = $this->input->post('id');
$input['name'] = $this->input->post('name');
$input['gender'] = $this->input->post('gender');
$input['email'] = $this->input->post('email');
$input['mobile'] = $this->input->post('mobile');
$input['department'] = 'test';//$this->input->post('department');
$input['isActive'] = 1;//$this->input->post('isActive');
$input['photo'] = 'testphoto';//$this->input->post('photo');
$output["response"] = $this->usr->saveUser($input,$UserID); // call model query to save data into DB
$output["success"] = true;
}
catch (Exception $ex)
{
$output["success"] = false;
$output["error"] = $ex->getMessage();
}
echo json_encode((object)$output);
exit;
}
if this is for development and not production,you can use a proxy to get arround the issue. add a json file to your root project named 'proxy.configuration.json'
remember to change the target to your api in the example below
{
"/api/*": {
"target": "https://localhost:44362",
"secure": false,
"logLevel": "debug",
"changeOrigin": true
}
}
then run ng serve --proxy-config proxy.config.json
you have to add Authorization header key in Access-Control-Allow-Headers(in the backend)
Access-Control-Allow-Headers: Authorization (when you give like this it accepts specified headers only.means if you want to accept another key like authorization you have to mention that key name)
or
you can give like this also
Access-Control-Allow-Headers: *

Laravel CORS issue

I am calling a login method from subdomain on main domain, and I made a CORS middleware which should take care of it. However it doesn't work as expected.
I want to check if requests came from a specific domain, so I tried doing this:
public function handle($request, Closure $next)
{
if(!isset($_SERVER['HTTP_REFERER']))
return $next($request);
$originalDomain = config('session.domain');
$parsedUrl = parse_url($_SERVER['HTTP_REFERER']);
$splitDomain = explode('.', $parsedUrl['host'], 2);
$subdomain = $splitDomain[0];
$domain = $splitDomain[1];
$subdomainValid = ($parsedUrl['host'] != $originalDomain) && ($originalDomain == $domain);
if(!$subdomainValid)
return $next($request);
$allowedUrl = $parsedUrl['scheme'] . '://' . $subdomain . '.' . config('session.domain');
return $next($request)
->header('Access-Control-Allow-Origin', $allowedUrl)
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Origin, x-requested-with, x-csrf-token');
}
But the issue I'm having is that $_SERVER['HTTP_REFERER'] sometimes doesn't return the value I expect. Shouldn't it return origin of the request?
I actually changed referrer to origin and added this part of code which resolves my issue:
if (isset($_SERVER['HTTP_ORIGIN']))
$referrer = $_SERVER['HTTP_ORIGIN'];
else
$referrer = request()->url();

File is missing when trying to upload a model through API doing a PUT request - Multipart/form-data Requests - Laravel / PHP

I'm using Laravel for the backend for an Android app.
I want to update the user picture, but when uploading the file + additional data to my backend, the file is missing in the request:
dd($request->hasFile('avatar')); // false
dd($request->File('avatar')); // null
This is what I sent in Postman (by the way i'm using Passport):
// Headers
Accept: application/json
Authorization: Bearer {{token}}
Content-Type: multipart/form-data
// Body of the request
'avatar' -> the image (in postman)
This is some of my update method, the part that manage the file:
public function update(Request $request)
{
// ...
if($request->hasFile('avatar'))
{
$avatar = $request->file('avatar');
$filename = time() . '.' . $avatar->getClientOriginalExtension();
Image::make($avatar)->resize(300,300)->save('/path/' . $filename));
$user->avatar = $filename;
}
// ...
$user->save();
// ...
}
I don't know what am I doing wrong. Thanks in advance.
After some research, I could make it work but using a POST Request adding _method = PUT as param (http://www.someurl.dev?_method=PUT).
PUT request with files aren't handle properly -if i'm not wrong- on purpose
Anyway, is not the solution that I was looking.. but at least work.

How to set multiple header value in Slim Framework 3 to a web service with api key?

I'm new in Slim Framework 3. I have a problem to accessing web service that has a Api Key header value. I have had a Api Key value and wanna access the web service to get JSON data. Here is my slim get method code:
$app->get('/getbooking/{id}', function (Request $request, Response $response, $args) {
$id = $args['id'];
$string = file_get_contents('http://maindomain.com/webapi/user/'.$id);
//Still confuse how to set header value to access the web service with Api Key in the header included.
});
I have tried the web service in Postman (chrome app) to access and I get the result. I use GET method and set Headers value for Api Key.
But how to set Headers value in Slim 3 to get access the web service?
Thanks for advance :)
This doesn't actually have anything to do with Slim. There are multiple ways to make an HTTP request from within PHP including streams (file_get_contents()), curl and libraries such as Guzzle.
Your example uses file_get_contents(), so to set a header there, you need to create a context. Something like this:
$app->get('/getbooking/{id}', function (Request $request, Response $response, $args) {
$id = $args['id']; // validate $id here before using it!
// add headers. Each one is separated by "\r\n"
$options['http']['header'] = 'Authorization: Bearer {token here}';
$options['http']['header'] .= "\r\nAccept: application/json";
// create context
$context = stream_context_create($options);
// make API request
$string = file_get_contents('http://maindomain.com/webapi/user/'.$id, 0, $context);
if (false === $string) {
throw new \Exception('Unable to connect');
}
// get the status code
$status = null;
if (preg_match('#HTTP/[0-9\.]+\s+([0-9]+)#', $http_response_header[0], $matches)) {
$status = (int)$matches[1];
}
// check status code and process $string here
}

Passing Oauth2 token via query parameters when using PUT http verb?

I am using the league\oauth2-server and have it working perfectly when I am using the GET http verb.
However when doing a PUT request I am getting hit with
Call to undefined method League\OAuth2\Server\Util\Request::PUT()
The specific code that is throwing this error is a function Server/Resource.php file
$accessToken = $this->getRequest()->{$method}($this->tokenKey);
From the function
protected function determineAccessToken($headersOnly = false)
{
if ($header = $this->getRequest()->header('Authorization')) {
// Check for special case, because cURL sometimes does an
// internal second request and doubles the authorization header,
// which always resulted in an error.
//
// 1st request: Authorization: Bearer XXX
// 2nd request: Authorization: Bearer XXX, Bearer XXX
if (strpos($header, ',') !== false) {
$headerPart = explode(',', $header);
$accessToken = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $headerPart[0]));
} else {
$accessToken = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $header));
}
$accessToken = ($accessToken === 'Bearer') ? '' : $accessToken;
} elseif ($headersOnly === false) {
$method = $this->getRequest()->server('REQUEST_METHOD');
$accessToken = $this->getRequest()->{$method}($this->tokenKey);
}
if (empty($accessToken)) {
throw new Exception\InvalidAccessTokenException('Access token is missing');
}
return $accessToken;
}
I am using the POSTMAN request client to test the requests
Its throwing that error because PUT requests for the web service are not allowed. And that makes sense because you really should never need to do a PUT request for an OAuth2 request. PUT tells the RESTful service on the other end you are trying to update a specific entity. OAuth2 has no entities to update, only to retrieve.
Perhaps a better understanding of what you are trying to do might explain why you are using a PUT, but for OAuth2 it should always be a GET request.
if you set the 'http_headers_only' setting to true and send the token in the correct header, it should work.
By correct HTTP header I mean "Authorization: Bearer " instead of access_token: that can be seen in your postman screenshot. Also please note that "Authorization" is the key and the value consists of both "Bearer" keyword and your token, separated by a space character.

Categories