(XMLHttpRequest error) Problem with serverside CORS policy - dart

I created a flutter project with a web version and we already have a server for database access that another android/ios app uses. However the web version of the new app is running into problems with cors policy. I've been trying to solve this looking at other stock overflow questions and searching on google without success and was hoping someone can help me figure out what I might be doing wrong.
I've tested making the uri client side both with:
String url = "https://" + host + ":" + port;
Uri uri = Uri.parse(url + "/test");
and
String url = host + ":" + port;
Uri uri = Uri.https(url, "/test");
I then call the server using the http/http package:
Response response = await get(uri).timeout(const Duration(seconds: 17));
As for the structure of the server side code:
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const https = require('https');
const routerOne = require('./path/to/router/file');
const routerTwo = require('./path/to/router/file');
const dotenv = require('dotenv');
const fs = require("fs");
dotenv.config();
console.log('port' + process.env.PORT);
var key = fs.readFileSync('./certs/key.key');
var cert = fs.readFileSync('./certs/cert.crt');
var options = {
key: key,
cert: cert
};
const cors = require('cors');
const app = express();
app.use(cors());
try {
let server = https.createServer(options, app);
server.listen(process.env.PORT, () => {
console.log('Started https server on port ' + process.env.PORT);
});
} catch (err) {
console.log(err);
}
app.get('/test', cors(), function (req, res, next) {
res.json({msg: "This is CORS-enabled for all origins!"})
})
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({limit: '50mb', extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/router/one', routerOne);
app.use('/router/two', routerTwo);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
console.log(err);
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Unlike android when running web version(Chrome or Edge), I have been unable to get the response from the newly added '/test' on the server side. I'm hoping for some suggestion for how I can get the cors policy to work.
Client side I've tried using Uri.https instead of Uri.parse and I added headers as well.
On the server I tried to follow instructions on how to add cors policy to node.js/express.
Error message from flutter:
Error: XMLHttpRequest error.
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current
packages/http/src/browser_client.dart 69:22 <fn>
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1685:54 runUnary
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 147:18 handleValue
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 766:44 handleValueCallback
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 795:13 _propagateToListeners
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 557:7 [_complete]
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/stream_pipe.dart 61:11 _cancelAndValue
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/stream.dart 1530:7 <fn>
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 334:14 _checkAndCall
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 339:39 dcall
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/html/dart2js/html_dart2js.dart 37309:58 <fn>
at Object.createErrorWithStack (http://localhost:59072/dart_sdk.js:5093:12)
at Error._throw (http://localhost:59072/dart_sdk.js:20399:18)
at Error.throwWithStackTrace (http://localhost:59072/dart_sdk.js:20396:18)
at async._AsyncCallbackEntry.new.callback (http://localhost:59072/dart_sdk.js:40921:18)
at Object._microtaskLoop (http://localhost:59072/dart_sdk.js:40778:13)
at _startMicrotaskLoop (http://localhost:59072/dart_sdk.js:40784:13)
at http://localhost:59072/dart_sdk.js:36261:9
Image of browser: image of browser with network tab
Update Solution
The answer from Ber is correct. This is a problem with certificate. Self signed certificate was being used on our server and by getting a new certificate using Let's encrypt the problem got solved. If anyone else runs into the "XMLHttpRequest error" they may also want to check out the error output in the browser as the "net::ERR_CERT_AUTHORITY_INVALID" was not shown in flutter.

The error code in your screen shot is net::ERR_CERT_AUTHORITY_INVALID
meaning the server's SSL certificate is expired, invalid for the domain or not accepted by the root certificates in your app.

Related

Salesforce Authentication in NodeJs

I am trying to authenticate Salesforce to NodeJS application.I getting error Like Error: invalid_grant - authentication failure .What else I am missing here. Do I need to do any configurations from salesforce side. Here is my code. Could Someone help me on this?
app.js
var nforce = require('nforce');
const client_id = '**'
const client_secret = '****'
const redirect_uri = 'https://***.sandbox.my.salesforce.com/services/oauth2/success'
const sfdc_user = '*****'
const sfdc_pass = '***'
const credentials = {
client_id :client_id,
client_secret:client_secret,
grant_type:"password",
username:sfdc_user,
password:sfdc_pass
}
async function getConnection(){
const loginUrl = "https://***.sandbox.my.salesforce.com/services/oauth2/token";
var org = nforce.createConnection({
clientId: credentials.client_id,
clientSecret: credentials.client_secret,
redirectUri: redirect_uri,
});
console.log('org >>'+JSON.stringify(org));
let oauth= await org.authenticate({ username: credentials.username, password: credentials.password});
console.log('oauth >>'+oauth); //Couldnt get this console
const access_token = oauth.access_token;
const sf_auth_url = oauth.instance_url + '/services/data/v48.0/'
sf_auth = {
'Authorization':'Bearer ' + access_token,
'Content-type': 'application/json',
'Accept-Encoding': 'gzip'
}
return { sf_auth,sf_auth_url }
}
module.exports = { getConnection }
main.js
const f = require('./app');
const https = require('https')
const fs = require('fs')
const port = 3000
const server = https.createServer(function(req,res){
res.writeHead(200,{'Content-Type': 'text/html'})
res.end();
})
server.listen(port,function(error){
if(error){
console.log('Something Went Wrong!')
}else{
console.log('Server is listening on port '+port)
f.getConnection();
}
})
Usually when I have received this error it's due to not having the user's security security token appended to the end of the password field. This is the token sent to you via email when you first set your password or performed your last password reset. If you need to reset it you can do so via Personal Settings > Reset My Security Token
Reset Your Security Token
In the event it's not that, this username/password authentication documentation should help.
OAuth 2.0 Username-Password Flow for Special Scenarios

Ionic 5 - API request working on browser, not on emulated IOS

I have this Ionic 5/Capacitor app, which I'm making an API call to a local server from, that server running on docker at localhost:3000. When I test from the browser, the request is made fine. From Postman it requests fine, too. In my XCode logs the emulator, I see this
[error] - ERROR {"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status":0,"statusText":"Unknown Error","url":"http://localhost:3000/pins","ok":false,"name":"HttpErrorResponse","message":"Http failure response for http://localhost:3000/pins: 0 Unknown Error","error":{"isTrusted":true}}
The really interesting part, is that I'm running Fiddler to monitor the request as it's made. Fiddler gets a 200 as well, I can even see the response data. So, Fiddler sees the proper network call, but then my Ionic app gets that error. That makes me feel like it's an Ionic/Emulator/IOS problem, but I don't have enough familiarity with Ionic to know right off the bat what it is.
Here's the code responsible for making the request:
ngOnInit() {
const request = this.http.get('http://localhost:3000/pins');
this.refresh$.subscribe(
(lastPos: { latitude?: any; longitude?: number }) => {
request.subscribe(data => {
if (data) {
this.addMarkersToMap(data, lastPos);
}
});
}
);
}
And the HTTPClient imported in the constructor is from Angular:
import { HttpClient } from '#angular/common/http';
I ended up having to use this package, doing a check on if I'm on mobile or not.
https://ionicframework.com/docs/native/http/
Try with this :
const request = this.http.get('http://localhost:3000/pins', { observe: 'response', withCredentials: true });
Solution 2 : capacitor.config.json
"server": {
"hostname": "localhost", (maybe try precising the port number too)
}
Solution 3 : On your Express server (from https://ionicframework.com/docs/troubleshooting/cors)
const express = require('express');
const cors = require('cors');
const app = express();
const allowedOrigins = [
'capacitor://localhost',
'ionic://localhost',
'http://localhost',
'http://localhost:8080',
'http://localhost:8100'
];
// Reflect the origin if it's in the allowed list or not defined (cURL, Postman, etc.)
const corsOptions = {
origin: (origin, callback) => {
if (allowedOrigins.includes(origin) || !origin) {
callback(null, true);
} else {
callback(new Error('Origin not allowed by CORS'));
}
}
}
// Enable preflight requests for all routes
app.options('*', cors(corsOptions));
app.get('/', cors(corsOptions), (req, res, next) => {
res.json({ message: 'This route is CORS-enabled for an allowed origin.' });
})
app.listen(3000, () => {
console.log('CORS-enabled web server listening on port 3000');
});

Error while using superagent in react native ios app

i have made a react native app that used nodejs and express for backend, have cors enabled and which running on android but when i started porting the app for ios and run it in simulator iphone 6, it is running fine but when it comes to hit an api for that i used superagent give me this error.
Error: Request has been terminated
Possible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.
at Request.crossDomainError (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:80241:9)
at XMLHttpRequest.xhr.onreadystatechange (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:80311:13)
at XMLHttpRequest.dispatchEvent (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:10000:15)
at XMLHttpRequest.setReadyState (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:26063:6)
at XMLHttpRequest.__didCompleteResponse (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:25917:6)
at http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:26011:52
at RCTDeviceEventEmitter.emit (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:9233:23)
at MessageQueue.__callFunction (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:7213:34)
at http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:7104:8
at guard (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:7050:1)
this is how i use superagent
const request = require('superagent');
const req = request[options.method.toLowerCase()](options.uri)
.set(merge({}, options.headers, options.json ? {'Content-Type': 'application/json'} : {}))
.query(options.qs ? options.qs : {})
.send(options.json || options.form || options.formData)
;
const requestId = {};
api.activeRequests.add(requestId);
return new Promise((resolve, reject) => {
req.end((err, res) => {
console.log({err, res});
api.activeRequests.delete(requestId);
if (err || !res.ok) {
console.log(res);
const error = res ? (res.body ? res.body : res) : err;
reject(error);
} else {
resolve(res.body);
}
});
});
Need help!
It was due to https request to be posted not http. So as of now since i am in developer mode allowed http to my particular domain.

Parse.Cloud.afterSave for sending push notifications not working from Heroku server

I did the migration, from Parse to Heroku and everything went smooth. At this point I didn't have any cloud code or push notifications set up on Parse. When I was done with the migration I begin to implement cloud code to handle push notification every time I save a new text message, but the Parse.Cloud.afterSave method is not running. I know main.js is working because if I implement
Parse.Cloud.define('hello', function(req, res) {
res.success('Hi');
});
I get "Hi" return to my console in Xcode, but for some reason Parse.Cloud.afterSave does nothing. I also know my Parse.Cloud.afterSave code is correct because it's that same code I use on another app through parse though. What am I missing?
Here in my index.js file
var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var path = require('path');
var databaseUri = process.env.DATABASE_URI || process.env.MONGOLAB_URI;
if (!databaseUri) {
console.log('DATABASE_URI not specified, falling back to localhost.');
}
var api = new ParseServer({
databaseURI: databaseUri || '',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || '',
masterKey: process.env.MASTER_KEY || '',
fileKey: 'XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', // file key from parse
serverURL: process.env.SERVER_URL || '',
push: {
ios: {
pfx: '/Users/alexcruz/Desktop/Certificates.p12', // The filename of private key and certificate in PFX or PKCS12 format from disk
bundleId: 'com.daps.DapsPush', // The bundle identifier associate with your app
production: false // Specifies which environment to connect to: Production (if true) or Sandbox
}
}
});
var app = express();
// Serve static assets from the /public folder
app.use('/public', express.static(path.join(__dirname, '/public')));
// Serve the Parse API on the /parse URL prefix
var mountPath = process.env.PARSE_MOUNT || '/parse';
app.use(mountPath, api);
// Parse Server plays nicely with the rest of your web routes
app.get('/', function(req, res) {
res.status(200).send('Make sure to star the parse-server repo on GitHub!');
});
// There will be a test page available on the /test path of your server url
// Remove this before launching your app
app.get('/test', function(req, res) {
res.sendFile(path.join(__dirname, '/public/test.html'));
});
var port = process.env.PORT || 1337;
var httpServer = require('http').createServer(app);
httpServer.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
// This will enable the Live Query real-time server
ParseServer.createLiveQueryServer(httpServer);
Here is my main.js file
//Push Notification for messages that are received
Parse.Cloud.afterSave("MXTMessage", function(request) {
var messageText = request.object.get('message');
var usersReceived = request.object.get('receiver');
var currentUser = Parse.User.current();
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.equalTo('user', usersReceived);
pushQuery.notEqualTo('user', currentUser);
Parse.Push.send({
where: pushQuery, // Set our Installation query
data: {
alert: "New message: " + messageText
}
}, {
success: function() {
// Push was successful
},
error: function(error) {
throw "Got an error " + error.code + " : " + error.message;
}
});
});
Thank you
As I am not allowed to comment, I'm going to have to put this in an answer, but just treat it as a comment:
Did you verify the function itself is actually never being called e.g. by adding a console.log at the beginning of the function, or could it be that push itself is not working (you can check that by sending pushes via REST API Calls)? For example, push seems to be broken in parse-server 2.2.0, I had to downgrade to 1.6.0 to get it working.
Workaround could be to create a cloud code function for sending the push and have this function explicitly called by the clients after the message has been saved on the server.
Also you should check this: https://github.com/ParsePlatform/parse-server/issues/301 as you are using Parse.User.current() in your code.
Also, I get the impression that parse-server is not really stable at this time. I experience many bugs using parse-server and Heroku that the app running on parse.com does not have.

How to configure nack/node on Rails project?

Does any one Has every configure nack for the Rails Projects I happen to tried the dummy code
var http = require('http');
var nack = require('nack');
var app = nack.createProcess("/home/viren/myapp/config.ru");
http.createServer(function (req, res) { app.proxy(req, res); }).listen(8124, "127.0.0.1");
but it reported me with the following error
events.js:94
throw new Error('addListener only takes instances of Function');
^ Error: addListener only takes instances of Function
at BufferedRequest. (events.js:94:11)
at Process. (/home/viren/node_modules/nack/lib/process.js:257:21)
at Process.proxy (/home/viren/node_modules/nack/lib/process.js:3:63)
at Server. (/home/viren/simple.proxy.js:7:7)
at Server.emit (events.js:67:17)
at HTTPParser.onIncoming (http.js:1124:12)
at HTTPParser.onHeadersComplete (http.js:108:31)
at Socket.ondata (http.js:1019:22)
at Socket._onReadable (net.js:683:27)
at IOWatcher.onReadable [as callback] (net.js:177:10)
here is my custom rack-file
require "config/environment"
use Rails::Rack::LogTailer
use ActionDispatch::Static
run ActionController::Dispatcher.new
According the source at node_modules/nack/lib/process.js:257 nack is expecting app.proxy to have a signature of app.proxy(req, res, next) with is a common idiom with connect apps. In connect, calling next("some value") is a convention as most apps have a catch all error handler at the bottom of the middleware chain. Since your not using connect, just create your own error handler.
I also created a pull request, so hopefully using next will be optional in the future. https://github.com/josh/nack/pull/25
var http = require('http'); var nack = require('nack');
var app = nack.createProcess("/home/viren/myapp/config.ru");
http.createServer(function (req, res) { app.proxy(req, res, logNackError); }).listen(8124, "127.0.0.1");
function logNackError(err) {
console.log('nack error:', err);
}

Resources