Cant get local Api call work with Vue and Codeigniter - api

My wish: Making api calls on my local develoment environment.
My Problem: i use Headers for authorization, but my custom header is never seen in my api so the response is always 403 forbidden.
I'm new to creating Vue apps i've used the Vue CLI to create a local develop environment running on http://localhost:8080/ via npm run serve
Next to this ive created an own API with codeigniter (v2) its a simple straight forward api with 1 controller handling a couple of requests. I'm running this API on a local MAMP installation. with Url http://apiname.myname.local.
In Vue ive used mounted to start the API call. Ive tried this with axios, fetch, XMLHttpRequest and superagent. None of these seem to work.
In the MAMP apache config (httpd.conf) ive added this:
`< Directory />
Options Includes
AllowOverride All
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, PUT, POST, DELETE, OPTIONS"
Header always set Access-Control-Allow-Headers "authorization, Content-Type, X-Auth-Token,
Origin, Authorization, X-Auth-Token, x-auth-token"
< /Directory>`
And also this variant:
`< Directory />
Options Includes
AllowOverride All
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "*"
Header always set Access-Control-Allow-Headers "*"
< /Directory>`
In the Codeigniter Controller contructor ive added this:
`header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: x-auth-token, X-Auth-Token, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Authorization");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");`
And also this variant:
`header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: *");
header("Access-Control-Allow-Methods: *");`
In the vue app ive tried these:
`axios({
method: 'get',
headers: {
'Authorization': 'Whatever',
'X-Auth-Token': 'Whatever'
},
url: 'local_api_url'
}).finally(function () {
alert("ja");
});`
Or this (tried with and without the cors option. and with and without the credentials option.
`fetch('local_api_url',{
method: 'GET',
mode: 'no-cors',
headers: {
'Authorization': 'Whatever',
'X-Auth-Token': 'Whatever',
}
})`
Or this
`var x = new XMLHttpRequest();
x.open("GET","local_api_url");
x.setRequestHeader("Authorization","Whatever");
x.setRequestHeader("X-Auth-Token","Whatever");
x.send();`
None work.
Also in the Chrome Dev tools it looks like the header is never added to the request (well i think so) When i open the request in the network tab and click the tab Headers these are the Request Headers.
`Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: nl,de-DE;q=0.9,de;q=0.8,nl-NL;q=0.7,en-US;q=0.6,en;q=0.5
Access-Control-Request-Headers: authorization,x-auth-token
Access-Control-Request-Method: GET
Cache-Control: no-cache
Connection: keep-alive
Host: local_api_url
Origin: http://localhost:8080
Pragma: no-cache
Referer: http://localhost:8080/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36`
And the response headers:
`Access-Control-Allow-Headers: authorization, Content-Type, X-Auth-Token, Origin, Authorization, X-Auth-Token, x-auth-token
Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
Date: Fri, 06 Dec 2019 10:52:20 GMT
Keep-Alive: timeout=5, max=100
Server: Apache
Set-Cookie: ci_session_blabla
Set-Cookie: ci_session_blabla
Set-Cookie: ci_session_blabla
Set-Cookie: ci_session_blabla
Set-Cookie: ci_session_blabla
Set-Cookie: ci_session_blabla
Transfer-Encoding: chunked
X-Powered-By: PHP/7.2.14`
Ive also tried all this with a Vue proxy by creating a vue.config.js with this content:
`module.exports = {
devServer: {
proxy: 'local_api_url'
}
}`
Im using this code in Codeigniter to het the headers.
`$headers1 = getallheaders();
$headers2 = $this->input->request_headers();
$header_present = array_key_exists('X-Auth-Token', $headers);`
Whatever ive tried, also different combinations of the above, $header_present is always False!
So basically i think ive tried all solutions presented in other topics (and other sites like Github) and now ive no idea how to fix this and seriously consider to do authentication trough the body of the request instead of the header. Can someone help me?

Ive got the following working: in MAMP ive added this to the httpd.conf:
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
now ive used this code in my app:
axios({
method: 'GET',
url: 'loal_api_url',
headers: {
'Authorization': 'Bearer api_key'
}
})
This seems to work, im receiving the Authorization header now in my API. But im receiving 2 requests and the Authorization header is only filled in the second request.
For now ive used the following code in my API to only check the Authorization when:
if ($_SERVER['REQUEST_METHOD'] != 'OPTIONS') {
if (!array_key_exists('Authorization', $headers){
ALLOW REQUEST
}
}
And also in my data response:
$return = "OKAY";
if ($_SERVER['REQUEST_METHOD'] != 'OPTIONS') {
$return = $retval;
}
http_response_code(200);
header('Content-type: application/json');
die(json_encode($return));

Related

CORS with Flask, axios and https not working (response header sends origin as http instead of https)

My frontend (Expo Go web) is running at http://localhost:19006/ but when it receives a response from the backend, it somehow believes it runs under https://localhost:19006/
Also, the iOS version of Expo Go logs the following error:
LOG [AxiosError: Network Error]
I'm using Flask in the backend with CORS set as follows:
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['CORS_HEADERS'] = 'Content-Type'
app.config['SECRET_KEY'] = os.environ.get("SECRET_KEY", 'xxx')
cors = CORS(app, resources={r"/*": {"origins": "*", "allow_headers": "*", "expose_headers": "*", "Access-Control-Allow-Origin": "*"}})
and a simple return function:
#app.route("/matches", methods=["GET"])
def getMatches():
print('request for matches')
response = matches.getMatches()
return response
if __name__ == '__main__':
app.run(ssl_context=('certs/cert.pem', 'certs/key.pem'))
My frontend part is using react native with Expo Go. The query to the backend is done this way:
export default function App() {
const axiosApiCall = () => {
const config = {
headers:{
'origin': 'https://localhost:19006' #<- Here also tried http but no change
}
};
axios
.get("https://127.0.0.1:5000/matches", config)
.then((response) => {
setState({quote : 'yes'});
console.log(response.data);
})
.catch((error) => {
console.log(error);
})
}
The backend works properly fine as I can see in Postman. The result is technically showing up in the response of the web-version of Expo Go, however, it appears that there's an issue with CORS:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://127.0.0.1:5000/matches. (Reason: CORS header ‘Access-Control-Allow-Origin’ does not match ‘https://localhost:19006’).
And here's the response header:
HTTP/1.1 200 OK
Server: Werkzeug/2.2.2 Python/3.9.16
Date: Thu, 05 Jan 2023 10:16:42 GMT
Content-Type: application/json
Content-Length: 274552
Access-Control-Allow-Origin: http://localhost:19006
Access-Control-Expose-Headers: *
Vary: Origin
Connection: close
GET /matches HTTP/1.1
Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:108.0) Gecko/20100101 Firefox/108.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Origin: http://localhost:19006
DNT: 1
Connection: keep-alive
Referer: http://localhost:19006/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
Sec-GPC: 1
Anyone any idea? Thanks!!!
Hardcoding the CORS origins: no change
Changing the query from axios to async fetch calls: no change
Including/modifying the header in the axios config: no change
Other browsers: no change
Deactivating SSL in the backend: caused other problems related to react native

"Authorization": token does not pass CORS VUEJS APACHE

My FrontEnd Vue
var config = {
method: 'get',
url: baseUrl + '/v5/test',
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": Token,
},
};
My htaccess file
RewriteCond %{HTTP:Authorization} ^(.)
RewriteRule . - [e=HTTP_AUTHORIZATION:%1]
SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0
Header always set Access-Control-Allow-Origin ""
Header always set Access-Control-Allow-Methods ""
Header always set Access-Control-Allow-Headers: "Authorization"
Header always set Access-Control-Request-Headers: "Authorization"
i'm getting that error
Access to XMLHttpRequest at 'mydomain.com/v5/test' from origin 'app.mydomain.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
My app is subdomain and API are in domain
This is the headers that I am using for CORS
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
Access-Control-Allow-Methods: PUT, POST, PATCH, DELETE, GET
I don't know exactly what you are trying to achieve with that .htaccess
Hi guys I fixed doing couple changes
first I add this one in my vue.config.js
if you want to build and deploy you just need to uncomment first one to server and second one to local environment
devServer: {
//proxy: "https://subdomain.example.com/"
//proxy: "http://localhost/" // run in local
},
Second
In your server I add the htaccess this one:
<IfModule mod_headers.c>
SetEnvIf Origin "http(s)?://(subdomain)\.example\.com$" AccessControlAllowOrigin=$0
Header set Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
Header unset Connection
Header set Connection keep-alive
Header unset Keep-Alive
Header set Keep-Alive timeout=100,max=500
</IfModule>
Thats it the CORS was fixed

Status code 415 although headers all seem to be correct

I have an API call on my front end application that uses Axios to make a PUT request. This works from postman but in the browser I get the 415 error. Here are the browser headers:
General
Request URL: api.example.com/foo
Request Method: OPTIONS
Status Code: 415 Unsupported Media Type
Remote Address: ip.address:443
Referrer Policy: no-referrer-when-downgrade
Response Headers
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Methods: GET, PUT, POST, DELETE, HEAD, OPTIONS
Access-Control-Allow-Origin: *
Content-Length: 175
Content-Type: application/problem+json; charset=utf-8
Date: Mon, 13 Jan 2020 20:03:06 GMT
Request-Context: appId=guid
Server: Microsoft-IIS/10.0
Strict-Transport-Security: max-age=2592000
X-Powered-By: ASP.NET
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: PUT
Cache-Control: no-cache
Connection: keep-alive
Host: api.example.com
Origin: http://localhost:3000
Pragma: no-cache
Referer: http://localhost:3000/extension
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36
My request looks like this:
const url = 'https://api.example.com/foo';
const headers = {
'Content-Type': 'application/json; charset=UTF-8'
};
const data = JSON.stringify([{"name": "SomeName","date": "2020-01-30T14:50:56.636Z"}]);
axios.put(
url,
data,
{headers: headers}
)
.then(res => {
console.log(res);
})
.catch((e) => {
console.log(e);
});
My API is a .net core application. Thank you friends!
I figured out the problem; in the API, the options handlers had some parameters (since I copy pasta'd the PUT request for options) and the browser wasn't sending the parameters in the preflight check, so I was getting 415. Once I removed the parameters, it worked fine!

Office add-in: XMLHttpRequest cannot load XXX due to access control checks

I'm building an Outlook add-in with jQuery and the Office JS API. I have a local server going while developing, and I'm trying to submit a POST request to an endpoint on my site's main server. Every time I try to submit the request, I get the following three errors:
Origin https://localhost:3000 is not allowed by Access-Control-Allow-Origin
XMLHttpRequest cannot load https://myurl.com/my_endpoint due to access control checks
Failed to load resource: Origin https://localhost:3000 is not allowed by Access-Control-Allow-Origin
What I've done so far:
Found this related thread: HTTP fetch from within Outlook add-ins
The only answer says to do three things:
Make the request with XMLHttpRequest. Yup, did that:
function submitForm(var1, var2) {
var http = new XMLHttpRequest();
var params = 'var1=' + encodeURIComponent(var1) + '&var2=' + encodeURIComponent(var2);
http.open("POST", 'https://myurl.com/my_endpoint', true);
http.setRequestHeader('Access-Control-Allow-Origin', 'https://localhost:3000');
http.setRequestHeader('Access-Control-Allow-Credentials', true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {
console.log("response:", http.responseText);
console.log("status:", http.status);
};
http.send(params);
}
Add the service URL into the manifest's AppDomains list. Yup, did that, too. This is from my manifest.xml:
<AppDomains>
<AppDomain>https://myurl.com</AppDomain>
<AppDomain>https://myurl.com/my_endpoint</AppDomain>
<AppDomain>https://localhost:3000</AppDomain>
</AppDomains>
Use only services which are under SSL connection. Yup, the myurl.com server is only accessible via SSL.
I also found this documentation (https://learn.microsoft.com/en-us/office/dev/add-ins/develop/addressing-same-origin-policy-limitations) that recommends to solve this with cross-origin-resource-sharing (CORS), and points to this link: https://www.html5rocks.com/en/tutorials/file/xhr2/#toc-cors
So, I checked the server set-up for https://myurl.com and I am in fact allowing requests from any origin. UPDATE 1: as an example, here's what the output of a successful network request to https://myurl.com/my_endpoint looks like (notice the Accept: */* header):
Request URL: https://myurl.com/my_endpoint
Request Method: POST
Status Code: 200 OK
Referrer Policy: no-referrer-when-downgrade
Cache-Control: no-cache, no-store, must-revalidate, public, max-age=0
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Expires: 0
Pragma: no-cache
Server: nginx/1.10.3 (Ubuntu)
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 52
Content-type: application/x-www-form-urlencoded
Host: myurl.com
Origin: chrome-extension://focmnenmjhckllnenffcchbjdfpkbpie
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
var1: var1
var2: var2
Plus, another thing leading me to believe the problem isn't with https://myurl.com is: when I open my network tab in my debugger, I can see that my request never reaches https://myurl.com. I'm also not seeing the request pings in my https://myurl.com server logs. This is the output of my network request when I try to ping https://myurl.com from the Outlook add-in:
Summary
URL: https://myurl.com/my_endpoint
Status: —
Source: —
Request
Access-Control-Allow-Origin: https://localhost:3000
Access-Control-Allow-Credentials: true
Content-Type: application/x-www-form-urlencoded
Origin: https://localhost:3000
Accept: */*
Referer: https://localhost:3000/index.html?_host_Info=Outlook$Mac$16.02$en-US
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14) AppleWebKit/605.1.15 (KHTML, like Gecko)
Response
No response headers
Request Data
MIME Type: application/x-www-form-urlencoded
var1: var1
var2: var2
Any recommendations for what else I need to change to enable making a POST request to myurl.com? Thanks in advance to the kind soul that helps me figure this out.
UPDATE 2: For what it's worth, I haven't done any configs to my node server beyond what came out-of-the box when I ran npm install -g generator-office. E.g. I haven't touched these two files:
.babelrc
{
"presets": [
"env"
]
}
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
polyfill: 'babel-polyfill',
app: './src/index.js',
'function-file': './function-file/function-file.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
},
{
test: /\.html$/,
exclude: /node_modules/,
use: 'html-loader'
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: 'file-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
chunks: ['polyfill', 'app']
}),
new HtmlWebpackPlugin({
template: './function-file/function-file.html',
filename: 'function-file/function-file.html',
chunks: ['function-file']
})
]
};
Failed to load resource: Origin https://localhost:3000 is not allowed by Access-Control-Allow-Origin
The server responds to your pre-flight request (usually OPTIONS) and does not allow to get a response, that's because your origin localhost:3000 is not allowed on server side.
You need to respond to OPTIONS on server with 204 status code and a header like:
Access-Control-Allow-Origin 'localhost';

ember-simple-auth oauth2 authorizer issue

I am trying to set up authorization on an Ember App running on a Node.js server.
I am using the oauth2 Authenticator, which is requesting a token from the server. This is working fine. I am able to provide the app with a token, which it saves in the local-storage.
However, when I make subsequent requests, the authorizer is not adding the token to the header, I have initialized the authorizer using the method described in the documentation (http://ember-simple-auth.simplabs.com/ember-simple-auth-oauth2-api-docs.html):
Ember.Application.initializer({
name: 'authentication',
initialize: function(container, application) {
Ember.SimpleAuth.setup(container, application, {
authorizerFactory: 'authorizer:oauth2-bearer'
});
}
});
var App = Ember.Application.create();
And I have added an init method to the Authorizer, to log a message to the server when it is initialized, so I know that it is being loaded. The only thing is, the authorize method of the authorizer is never called.
It feels like I am missing a fundamental concept of the library.
I have a users route which I have protected using the AuthenticatedRouteMixin like so:
App.UsersRoute = Ember.Route.extend(Ember.SimpleAuth.AuthenticatedRouteMixin, {
model: function() {
return this.get('store').find('user');
}
});
Which is fetching the data, fine, and redirects to /login if no token is in the session, but the request headers do not include the token:
GET /users HTTP/1.1
Host: *****
Connection: keep-alive
Cache-Control: no-cache
Pragma: no-cache
Accept: application/json, text/javascript, */*; q=0.01
Origin: *****
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36
Referer: *****
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Any help you could give me would be greatly appreciated.
Is your REST API served on a different origin than the app is loaded from maybe? Ember.SimpleAuth does not authorizer cross origin requests by default (see here: https://github.com/simplabs/ember-simple-auth#cross-origin-authorization)