Trying to get auth0 working with my electron app. When I follow the default tutorial and try to authenticate with Username-Password-Authentication, the lock fails with a 403 error and responds with "Origin file:// is not allowed".
I've also added "file://*" to the Allowed Origins (CORS) section of my client settings in the auth0 dashboard.
Auth0 Lock with console errors
Origin file:// is not allowed
EDIT:
Lock setup in electron
var lock = new Auth0Lock(
'McQ0ls5GmkJRC1slHwNQ0585MJknnK0L',
'lpsd.auth0.com', {
auth: {
redirect: false,
sso: false
}
});
document.getElementById('pill_login').addEventListener('click', function (e) {
e.preventDefault();
lock.show();
})
I was able to get Auth0 to work by using an internal express server in my electron app to handle serving pages.
First I created a basic express app in a separate folder in my project called http, here will be the express server code and html files to serve.
const path = require('path');
const express = require('express');
const app = express();
app.use(express.static(process.env.P_DIR)); // Serve static files from the Parent Directory (Passed when child proccess is spawned).
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:<PORT>'); // Set this header to allow redirection from localhost to auth0
next();
})
// Default page to serve electron app
app.get('/index', (req, res) => {
res.sendFile(__dirname + '/index.html');
})
// Callback for Auth0
app.get('/auth/callback', (req, res) => {
res.redirect('/index');
})
// Listen on some port
app.listen(<SOME_PORT>, (err) => {
if (err) console.log(err);
console.log('HTTP Server running on ...');
});
Then in the Electron main process, I spawn the express server as a child process
const {spawn} = require('child_process');
const http = spawn('node', ['./dist/http/page-server.js'], {
env: {
P_DIR: __dirname // Pass the current dir to the child process as an env variable, this is for serving static files in the project
}
});
// Log standard output
http.stdout.on('data', (data) => {
console.log(data.toString());
})
// Log errors
http.stderr.on('data', (data) => {
console.log(data.toString());
})
Now the auth0 lock authenticates as expected.
Related
Background
I am migrating an Angular app in GKE cluster. The base docker image that I must use(company policy) does not have any options to install any new softwares like shell, Angular cli command ng etc. The base docker image has only Node installed.
There is a shared base url, let's say, www.my-company.com, that everyone has to use for app deployment with a path added after the base url like www.my-company.com/my-angular-app/ - all the other Angular apps must be differentiated using the path of the app.
What I did
Since I can't run ng serve command in the base image, I added Express dependency in the package.json in Angular application and created an express server to route the traffic to Angular app.
I was following this youtube video to configure the application - https://www.youtube.com/watch?v=sTbQphoYbK0&t=303s. The problem I am facing is to how I load the the static files in the application.
If I define absolute path inside sendFile method of server.js file, although the application is working, but in future, if I need to add any other files in the application, I have to create another route in server.js file.
I don't know how Express can search a file automatically from the static folder(and sub folders) and return only that file when needed. I defined a static folder too, but seems like it is not working.
Following is my server.js code
==============================
const express = require('express');
const http = require('http');
const path = require('path');
const port = 8080;
const contextPath = '/my-angular-app';
const router = express.Router();
const app = express();
app.use(contextPath, router);
app.listen(port, ()=> {
console.log("Listening on port: ", port);
});
app.use(express.static(__dirname + '/dist/testapp/'));
router.get('/', function(req, res) {
// to get index.html file
res.sendFile(path.resolve(__dirname + '/dist/testapp/index.html'));
});
router.get('/*', function(req, res) {
let path = __dirname +'/dist/testapp/' + req.path
console.log('full path: ', path);
// To return static files based on incoming request, I am facing problem here(I think)
res.sendFile(path);
});
==============================
I want Express will send any files based on file name in the request. It should also take care of nested directories in the /dist/testapp/ directory
/dist/testapp/ -> This is the directory where Angular generates code for my app after I execute ng build command
WEBAPP.get("/admin/script.js", (req, res) => {
console.log(req.path);
if (req.session.username !== "Admin") return res.render("error");
res.sendFile(__dirname + "/admin/admin.js")
});
WEBAPP.get("/admin", (req, res) => {
if (!req.session.loggedin) return res.render("error");
if (req.session.username !== "Admin") return res.render("error",);
res.render("admin", {
csrfToken: req.csrfToken(),
title: "ADMIN PORTAL",
username: req.session.username,
nav_avatar: GetImageURL(req.session.avatar, "small")
});
});
There's no need to publically share /admin/script.js in my case but if a user requests this URL say example.com/admin/script.js a check for username equaling "Admin" if all is okay we sendFile.
I would maybe assume that you're not properly targeting your static files. Perhaps console.log the target.
First a quick preface I think may be helpful: I am new to splitting my client and server into separate web apps. My previous apps have all had my server.js at the root level in my directory and the client (typically a create-react-app) in a /client folder.
What I wanted to do: Host a single express.js server on the web which multiple other web applications could make requests to.
I did the first part using an express server and aws elastic beanstalk.
server.js
require('dotenv').config()
const express = require('express');
const app = express();
const cors = require('cors');
const PORT = process.env.PORT || 5000;
const Mongoose = require('mongoose');
const { Sequelize } = require("sequelize");
//ROUTES
const APIUser = require('./routes/api/mongo/api-user');
more routes...
//INITIATE DATA MAPPING CONNECTIONS START
Mongoose.connect(
process.env.MONGO_URI,
{ useNewUrlParser: true, useUnifiedTopology: true },
console.log("connected to MongoDB")
);
const Postgres = new Sequelize(process.env.PG_CONN_STRING);
try {
Postgres.authenticate()
.then(console.log("connected to Postgres"));
} catch {
console.log("Postgres connection failed")
}
//INITIATE DATA MAPPING CONNECTIONS END
//middleware
app.use(cors())
more middleware...
//home route
app.get('/api', (req, res) => {
console.log('RECEIVED REQ to [production]/api/')
res.status(200).send('models api home').end();
})
//all other routes
app.use('/api/user', APIUser);
more route definitions...
//launch
app.listen(PORT, () => console.log(`listening on port ${PORT}`));
The log file for successful boot up on aws: https://imgur.com/vLgdaxK
At first glance it seemed to work as my postman requests were working. Status 200 with appropriate response: https://imgur.com/VH4eHzH
Next I tested this from one of my actual clients in localhost. Here is one of my react client's api util files where axios calls are made to the backend:
import { PROXY_URL } from '../../config';
import { axiosInstance } from '../util';
const axiosProxy = axios.create({baseURL: PROXY_URL}); //this was the most reliable way I found to proxy requests to the server
export const setAuthToken = () => {
const route = "/api/authorization/new-token";
console.log("SENDING REQ TO: " + PROXY_URL + route)
return axiosProxy.post(route)
}
export const authorize = clientsecret => {
const route = "/api/authorization/authorize-survey-analytics-client";
console.log("SENDING REQ TO: " + PROXY_URL + route)
return axiosProxy.post(route, { clientsecret })
}
Once again it worked... or rather I eventually got it to work: https://imgur.com/c2rPuoc
So I figured all was well now but when I tried using the live version of the client the request failed somewhere.
in summary the live api works when requests are made from postman or localhost but doesn't respond when requests are made from a live client https://imgur.com/kOk2RWf
I have confirmed that the requests made from the live client do not make it to the live server (by making requests from a live client and then checking the aws live server logs).
I am not receiving any Cors or Cross-Origin-Access errors and the requests from the live client to the live server don't throw any loud errors, I just eventually get a net::ERR_CONNECTION_TIMED_OUT. Any ideas where I can look for issues or is there more code I could share?
Thank you!
Add a console.log(PROXY_URL) in your client application and check your browser console if that's logged correctly.
If it works on your local client build, and through POSTMAN, then your backend api is probably good. I highly suspect that your env variables are not being set. If PROXY_URL is an emplty string, your axios requests will be routed back to the origin of your client. But I assume they have different origins since you mention that they're separate apps.
Remember environment variables need to prefixed with REACT_APP_ and in a production build they have to be available at build time (wherever you perform npm run build)
I'm trying to learn nodejs and express and i created a simple server. I want to run some JS code for response.
When I used this method it's works.
const express = require('express');
const path = require('path');
require('dotenv').config();
const app = express();
const port = process.env.PORT || "8000";
app.get('/', (req, res) => {
res.send(`<script>
console.log("Program works!");
</script>`);
});
app.listen(port, () => {
console.log(`Listening to requests on http://localhost:${port}`);
});
But writing JS as String is hard so I tried this:
const express = require('express');
const path = require('path');
require('dotenv').config();
const app = express();
const port = process.env.PORT || "8000";
app.get('/', (req, res) => {
res.send(`<script src="./response.js"></script>`);
});
app.listen(port, () => {
console.log(`Listening to requests on http://localhost:${port}`);
});
And i get this error:
GET http://localhost:8000/response.js net::ERR_ABORTED 404 (Not Found)
When you send this:
<script src="./response.js"></script>
to the browser, the browser will parse that and see the src attribute and will then immediately request ./response.js from your server. But your server doesn't have any route to respond to that request (thus it gets a 404 error back from your server). Remember that a nodejs server serves NO files by default (unlike some other web servers). So, you have to create routes or middleware for anything that you want it to serve.
So, you need to add a route to your server that will response to a request for response.js. First change your <script> tag to this:
<script src="/response.js"></script>
You want the request to be "path absolute" so it does not depend upon the path of the containing page. Then, you need to add a route handler for response.js to your server.
This can be done as a single route:
app.get('/response.js', (req, res) => {
res.sendFile("response.js", {root: __dirname});
});
Or, you can use express.static() to serve a whole directory of publicly available files with one line of code (if you also move all publicly available static files to their own directory away from your server files).
I' trying to deploy an Vue app which has a separate backend and which will be hosted in different domain. For example:
meow.cat.xyz (App)
api.meow.cat.xyz (API)
Now after npm run build I tried to preview it locally by running serve -s dist and the application is severing at localhost:5000. However the problem is it not sending API request at the current end point (which is localhost:8000 at local and api.meow.cat.xyz at server). I tried config CORS as following
vue.config.js
module.exports = {
devServer: {
port: process.env.VUE_APP_DEV_PORT,
proxy: process.env.VUE_APP_API_ROOT_PATH,
},
};
.env.development
VUE_APP_API_ROOT_PATH = 'http://localhost:8000/api'
VUE_APP_DEV_PORT = 3000
Note that I'm using axiox. Here is my axios setup.
API.js
import axios from "axios";
const injectAccessToken = (config) => {
const accessToken = localStorage.getItem("access_token");
if (accessToken)
config.headers.common["Authorization"] = `Bearer ${accessToken}`;
return config;
};
const config = {
baseURL: process.env.VUE_APP_API_ROOT_PATH,
};
const API = axios.create(config);
API.interceptors.request.use(injectAccessToken);
export default API;
and Using it as following
Login.vue
import API from "#/api/Api";
<script>
const res= await API.post('login')
</script>
This solution is not working yet. Its sending request at http://localhost:5000. What's the point ? Note that I'm using axios. thanks in advance.
Allow CORS requests from the server
With the Access-Control-Allow-Origin header, you can specify what origins can use your API.
app.get('/api', (req, res) => {
res.set('Access-Control-Allow-Origin', 'http://localhost:3000');
res.send({
api: "your request."
});
})
Allow CORS from the app's origin on the server (api).
This has nothing to do with with the client (app)
I just got an existing project with react and node.js
When I run the react app the server call fails,
the React is on 8080,
the server looks something like this
// Listening on port 3000 for testing and 80 for prodution
app.listen(3000, function () {
winston.log('info', 'Listening on port 3000!');
});
// Index is currently inactive
app.get('/', function (req, res) {
res.send('');
});
// Call and load React
app.get('/app', function(req, res) {
res.sendFile(path.resolve(__dirname, 'public/index.html'));
});
// API for Web App
app.use('/api/v1', routes)
// API for Mobile App
app.use('/mapi/v1', mroutes)
// DEFINE ERROR BEHAVIOUR
// =============================================================================
// catch 404 and forward to error handler
app.use(function(req, res, next) {
res.status = 404;
res.sendFile(path.resolve(__dirname, 'public/index.html'));
// next(err);
});
this is how I got the project, I'm assuming it should work, I just need to make the node project somehow to run on port 8080(with the react app)
.
the client request is to localhost/8080(but changes depeneding on the port of the project),
if I'm runing react on 8081 the error will be "can't find localhost 8081/api/v1/GetUsers(example..)"
the means that the previous developer intended that the server and the client will be on the same port, but I don't how