Changin the base URL of loopback lb-services.js - javascript

I´m trying to get a client server and a rest api server to connect. I´m using angular js on frontend and loopback on backend.
on the lb-services.js I changed base url to:
var urlBase = 'http://localhost:3000/api';
My angular js is running on port 4000. But when I make a post to the rest api I get this error on my browser:
XMLHttpRequest cannot load http://localhost:3000/api/People. 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:4000' is therefore not allowed access. The response had HTTP status code 404.
Is there anyway I can proxy the connection or make both servers work together properly?
This is my gulp/server.js:
'use strict';
var path = require('path');
var gulp = require('gulp');
var conf = require('./conf');
var browserSync = require('browser-sync');
var browserSyncSpa = require('browser-sync-spa');
var util = require('util');
var proxyMiddleware = require('http-proxy-middleware');
function browserSyncInit(baseDir, browser) {
browser = browser === undefined ? 'default' : browser;
var routes = null;
if(baseDir === conf.paths.src || (util.isArray(baseDir) && baseDir.indexOf(conf.paths.src) !== -1)) {
routes = {
'/bower_components': 'bower_components'
};
}
var server = {
baseDir: baseDir,
routes: routes
};
/*
* You can add a proxy to your backend by uncommenting the line below.
* You just have to configure a context which will we redirected and the target url.
* Example: $http.get('/users') requests will be automatically proxified.
*
* For more details and option, https://github.com/chimurai/http-proxy-middleware/blob/v0.9.0/README.md
*/
server.middleware = proxyMiddleware('/api', {
target: 'http://localhost:3000/api',
changeOrigin: true
});
browserSync.instance = browserSync.init({
startPath: '/',
server: server,
browser: browser,
port:4000
});
}
browserSync.use(browserSyncSpa({
selector: '[ng-app]'// Only needed for angular apps
}));
gulp.task('serve', ['watch'], function () {
browserSyncInit([path.join(conf.paths.tmp, '/serve'), conf.paths.src]);
});
gulp.task('serve:dist', ['build'], function () {
browserSyncInit(conf.paths.dist);
});
gulp.task('serve:e2e', ['inject'], function () {
browserSyncInit([conf.paths.tmp + '/serve', conf.paths.src], []);
});
gulp.task('serve:e2e-dist', ['build'], function () {
browserSyncInit(conf.paths.dist, []);
});

Is there anyway I can proxy the connection or make both servers work
together properly?
It's surprising that you get this error as loopback enables CORS by default. It would be worth checking out the middleware.json file in your loopback server and see whether cors.params.origin is true. Here is the documentation link for your reference.
I'm not sure how you have changed the urlBase for accessing your rest api. I had done it using the angular module config as described here.

You can add CORS support to your LoopBack API:
https://docs.strongloop.com/display/public/LB/Security+considerations#Securityconsiderations-CORS

Related

Connecting to parse server from https://example.com fails

I'm trying to connect to the Parse server that is implemented in a VPS, from a website that served with apache.
The website is https://example.com, At first, when I tried to connect to parse server in Javascript codes, I did :
Parse.initialize("myAppId");
Parse.serverURL = 'http://ipOfVPS:1337/parse'
But I get mixed content: the page at '' was loaded over HTTPS .. error.
then I changed parse server Url in javascript to https://ipOfVPS:1337/parse and in the backend of parse server, I run the server with HTTPS. and now when I want to load the website of https://example.com, I get this error in chrome:
net::ERR_CERT_AUTHORITY_INVALID and this error in Firefox:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at.
I will be thankful if anybody helps me with this issue.
Here below I pasted my index.js:
// Example express application adding the parse-server module to expose Parse
// compatible API routes.
var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var path = require('path');
var databaseUri = process.env.DATABASE_URI || process.env.MONGODB_URI;
if (!databaseUri) {
console.log('DATABASE_URI not specified, falling back to localhost.');
}
var api = new ParseServer({
databaseURI: databaseUri || 'mongodb://localhost:27017/dev',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || 'XXXX',
masterKey: process.env.MASTER_KEY || 'XXXX', //Add your master key here. Keep it secret!
serverURL: process.env.SERVER_URL || 'https://localhost:1337/parse', // Don't forget to change to https if needed
liveQuery: {
classNames: ["Message","Chats"] // List of classes to support for query subscriptions
},
push: {
android: {
apiKey: 'XXX'
}
}
});
// Client-keys like the javascript key or the .NET key are not necessary with parse-server
// If you wish you require them, you can set them as options in the initialization above:
// javascriptKey, restAPIKey, dotNetKey, clientKey
var options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
requestCert: true,
//ca: fs.readFileSync('/etc/ssl/certs/ca.crt'),
rejectUnauthorized: false
};
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('I dream of being a website. Please 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 httpsServer = require('https').createServer(options,app);
httpsServer.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
// This will enable the Live Query real-time server
ParseServer.createLiveQueryServer(httpsServer);

Getting a variable from a Server script to a Client script

Here's the current issue i'm struggling with. I'm on a webapp project, in which I have 2 scripts :
A script called start.js in which I initialize the server and initialize a variable, token. This script is ran when I start the webapp.
A script called viewer.js which initialize a viewer. That viewer requires the previous token to work.
I can't generate the token from the client side, because it requires NodeJS, and as far as I understood NodeJS doesn't work on Client side.
I've tried to use global variables, global methods, or HTTP requests, but none of these methods seems to work so far. Any tip on how to do it ?
Here is what I tried:
// start.js
const ForgeSDK = require('forge-apis');
const express = require('express');
const path = require('path');
var app = express();
app.use('/static', express.static(__dirname + '/static'));
/**
* Token generation
*/
oAuth2TwoLegged.authenticate().then(function(credentials){
setToken(credentials.access_token)
}, function(err){
console.error(err);
});
function setToken(newToken) {
console.log("Definition du nouveau token")
token = newToken;
console.log(token)
};
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
});
app.listen(3000, function () {
console.log('Token provider listening on port 3000')
});
// viewer.js
var token = '';
/**
* Viewer initialization
*/
You can pass a callback to your config options to obtain the token (usually via ajax) to requests:
var options = {
env: 'AutodeskProduction',
getAccessToken: function(onGetAccessToken) {
//
// TODO: Replace static access token string below with call to fetch new token from your backend
// Both values are provided by Forge's Authentication (OAuth) API.
//
// Example Forge's Authentication (OAuth) API return value:
// {
// "access_token": "<YOUR_APPLICATION_TOKEN>",
// "token_type": "Bearer",
// "expires_in": 86400
// }
//
var accessToken = '<YOUR_APPLICATION_TOKEN>';
var expireTimeSeconds = 86400;
onGetAccessToken(accessToken, expireTimeSeconds);
}
}
Autodesk.Viewing.Initializer(options, function onInitialized(){
...
See here for details.
And see here and here to create an endpoint to generate access tokens in your Node backend.

Node http-proxy not working behind proxy

I am using the http-proxy-middleware module, which is an express middleware. the middleware module relies on http-proxy. The node host is running behind a proxy.
I want to forward certain routes to a different service (for test purposes let's assume httpbin.org). So I defined the proxy as follows.
var proxy = require('http-proxy-middleware');
var aeProxy = proxy({
target: 'http://httpbin.org',
changeOrigin: true,
pathRewrite: {
'^/api/ae':'/get'
}
});
app.use('/api/ae', proxy);
I have also set the respective env variables (from debugging console):
process.env.HTTP_PROXY
> "http://proxy:8080"
process.env.HTTPS_PROXY
> "http://proxy:8080"
Unfortunately I only get timeouts. When running the node script in an environment without a proxy it works as expected.
Is my configuration wrong?
Credit to chimurai for this on how to connect via a corporate proxy via the agent field.
var HttpsProxyAgent = require('https-proxy-agent');
var proxy = require("http-proxy-middleware");
// corporate proxy to connect to via environment variables
var proxyServer = process.env.HTTPS_PROXY ||
process.env.HTTP_PROXY;
var options = {
target: 'http://localhost:3000',//Proxy url
agent: new HttpsProxyAgent(proxyServer)//The actual corporate proxy sever
};
var apiProxy = proxy('/api', options);
If you are behind a V2Ray protocol, you can just set the listening address and port of your connection like bellow and you'r good to go.
var HttpsProxyAgent = require('https-proxy-agent');
const { createProxyMiddleware, fixRequestBody } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: process.env.REACT_APP_API_URL
changeOrigin: true,
secure: false,
logLevel: "debug",
onProxyReq: fixRequestBody,
agent: new HttpsProxyAgent('http://127.0.0.1:1087'),
headers: {
'X-Auth-Token': process.env.REACT_APP_API_TOKEN
},
pathRewrite: {
'^/api': ''
}
})
);
};

Securing Loopback with third party OpenID Connect

I'm trying to secure my loopback service with my third party OpenID Connect service (Keycloak) but it doesn't seem to be validating requests have accesstokens at all.
My server.js:
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = module.exports = loopback();
// Passport configurators..
var loopbackPassport = require('loopback-component-passport');
var PassportConfigurator = loopbackPassport.PassportConfigurator;
var passportConfigurator = new PassportConfigurator(app);
var cont = function(req, res){
next();
};
/**
* Flash messages for passport
*
* Setting the failureFlash option to true instructs Passport to flash an
* error message using the message given by the strategy's verify callback,
* if any. This is often the best approach, because the verify callback
* can make the most accurate determination of why authentication failed.
*/
var flash = require('express-flash');
// attempt to build the providers/passport config
var config = {};
try {
config = require('../providers.json');
} catch (err) {
console.trace(err);
process.exit(1); // fatal
}
// -- Add your pre-processing middleware here --
// boot scripts mount components like REST API
boot(app, __dirname);
// The access token is only available after boot
app.middleware('auth', loopback.token({
model: app.models.accessToken
}));
app.middleware('session:before', loopback.cookieParser(app.get('cookieSecret')));
app.middleware('session', loopback.session({
secret: 'kitty',
saveUninitialized: true,
resave: true
}));
passportConfigurator.init();
// We need flash messages to see passport errors
app.use(flash());
passportConfigurator.setupModels({
userModel: app.models.user,
userIdentityModel: app.models.userIdentity,
userCredentialModel: app.models.userCredential
});
for (var s in config) {
var c = config[s];
c.session = c.session !== false;
passportConfigurator.configureProvider(s, c);
}
var ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;
app.start = function () {
// start the web server
return app.listen(function () {
app.emit('started');
var baseUrl = app.get('url').replace(/\/$/, '');
console.log('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
var explorerPath = app.get('loopback-component-explorer').mountPath;
console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
};
// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function (err) {
if (err) throw err;
// start the server if `$ node server.js`
if (require.main === module)
app.start();
});
provider.json
{
"oAuth2": {
"provider": "keycloak",
"module": "passport-openidconnect",
"authorizationURL": "https://xxx",
"tokenURL": "https://xxxx",
"clientID": "xxx",
"clientSecret": "-",
"failureFlash": true
}
}
I've been trying to follow this example:
https://github.com/strongloop/loopback-example-passport
But that doesn't explain how to connect to an OpenID Connect service and secure my APIs.
I've also tried this for specific APIs:
app.get('/api/Clients', ensureLoggedIn('/login'), cont);
I want to really lock down all APIs and check if a valid token is presented in the query which should be validated by my third party authentication service.
Thanks in advance!

Cloudkit JS && Node JS

I'm currently trying to perform server side connection to iCloud Server using the new CloudKit JS from Apple. According to the WWDC 2015 "CloudKit JS and Web Service", since CloudKit JS is a pure JS framework, you can use it in all JS environnements such as node JS.
I copied the source code of CloudKit JS from https://cdn.apple-cloudkit.com/ck/1/cloudkit.js and pasted it in a file named "cloudkit.js". Here is a demo of what I tried :
var CloudKit = require("/some/folders/cloudkit.js")
function demoPerformQuery() {
CloudKit.configure({
containers: [{
containerIdentifier: 'myContainerIdentifier',
apiToken: 'myAPIToken',
environment: 'development'
}]
})
var container = CloudKit.getDefaultContainer();
var publicDB = container.publicCloudDatabase;
publicDB.performQuery({recordType: 'Items'}).then(function(response){
// never called :-(
})
}
var express = require('express')
var app = express()
app.get("/", function(){
demoPerformQuery()
})
var server = app.listen(8080, function () {
console.log("server launched")
})
CloudKit seems to be correctly set up since all the functions are correctly called. But the callback of performQuery is never called. Why ?
Is there someone who already succeed to configure CloudKit JS in an server environnement ?
Thanks in advance
In the browser, CloudKit.js relies on XmlHttpRequest in order to fetch resources, but since CloudKit isn't an npm module you'll need a way to fetch things from your server.
npm install node-fetch
Using node-fetch, here is a tweaked version of your code that logs the resulting Items in your query:
var fetch = require('node-fetch');
var CloudKit = require("./cloudkit.js")
CloudKit.configure({
services: {
fetch: fetch
},
containers: [{
containerIdentifier: 'yourContainerIdentifier',
apiToken: 'yourAPItoken',
environment: 'development'
}]
})
var container = CloudKit.getDefaultContainer();
var publicDB = container.publicCloudDatabase;
function demoPerformQuery() {
publicDB.performQuery({recordType: 'Items'}).then(function(response){
console.log(response)
}).catch(function(error){
console.log(error)
})
}
var express = require('express')
var app = express()
app.get("/", function() {
demoPerformQuery()
})
var server = app.listen(8080, function () {
console.log("Server listen")
})
After hitting http://localhost:8080 you should see your server log the response to your query.

Categories