Electron Webview get response - node.js

I am very new to electron so I may be going about this all wrong.
We have a few web apps internally that are all working and I wanted to practice by building one of them into electron.
What I need to do is load our SSO login page within the app and then listen for a cookie/session to be created after authentication has been successful.
I am using a webview like so:
<div style="width:100%; height:100%">
<span class="loading loader" id="loading" name="loading"></span>
<webview class="ssologin" src="https://example.com/resources/ldap.php" autosize="on" style="min-width:755px; min-height:640px"></webview>
</div>
This loads the login page for ldap/sso. After I login, it would normally take you to the web application you were going to before you were re-routed to SSO do to not having a valid session.
I am trying to figure out how I can listen for a cookie/session so that I know that they have authenticated and we get a response back.
Essentially, I need this valid session in order to make future API calls in the app to endpoints so I want to try and use this existing authentication implementation without having to include other modules and mess with all that.
Any suggestions?

Just in case you didn't know: Electron does not currently recommend to use <webview>:
We currently recommend to not use the webview tag and to consider alternatives, like iframe, Electron's BrowserView, or an architecture that avoids embedded content altogether.
Cf https://electronjs.org/docs/api/webview-tag#warning
You probably need to set a partition on your <webview>:
<webview src="https://github.com" partition="persist:github"></webview>
<webview src="https://electronjs.org" partition="electron"></webview>
Sets the session used by the page. If partition starts with persist:, the page will use a persistent session available to all pages in the app with the same partition. if there is no persist: prefix, the page will use an in-memory session. By assigning the same partition, multiple pages can share the same session. If the partition is unset then default session of the app will be used.
Cf https://electronjs.org/docs/api/webview-tag#partition
With that you can (from the main process) access the cookie of the session:
const {session} = require('electron');
const sess = session.fromPartition('persist:foobar');
const cookies = sess.cookies;
Then you can listen for changed events on that cookie object:
Emitted when a cookie is changed because it was added, edited, removed, or expired.
cookies.on('change', () => {
// do something when your SSO cookie is set
});
Cf https://electronjs.org/docs/api/cookies#event-changed

Related

How to get localStorage before rendering reactjs components in universal app?

I am storing "some" user's session data in the client's localStorage, I need to get this data after server rendering and before the reactjs app is loaded so I can check if the user session is valid. If the user session is valid, I update the redux store with the user data; otherwise, I leave it as is.
I am using react-router's onEnter hook to check if the user's session is valid. The problem is that I am requesting the data saved in the localStorage on the server side (which I know is not available).
Therefore, I need a way to check the localStorage after the server render and have it ready for the onEnter hook.
I would also like to know if there is a way, while on the server side, to request the client's localStorage?
You will need to sort out the logic in between createStore and render() in your client.js file.
import {createStore} from 'redux';
const store = createStore();
if(localStorage.get('token')) {
store.dispatch(authenticate(localStorage.get('token')));
}
render(
<Provider store={store}><App/></Provider>,
document.getElementById('js-react')
);
Keep in mind that if there is any asynchronous code in the authenticate action creator that you will then need to wait for it to finish before you can render.

Authentication & Sessions in express.js/sails.js

Have been working through the sails cast tutorials and am confused about the way that sessions work.
In the tutorial, the user is marked as authenticated in the session controller by:
req.session.authenticated = true;
req.session.User = user;
res.redirect('/');
Why is the session being saved in the request?! My understanding is that the 'req' object in express.js is the information the browser sends to the server.
Shouldn't the server save this information elsewhere (won't the request object be deleted when theres another request?)
Furthermore, somehow the application retrieves the authentication status from another object session when templating a page with ejs:
<% if (session.authenticated) { %>
why isn't this variable set directly?
Probably a silly question but I am confused at how the logic works and online articles/tutorials aren't helping me understand...
It is common practice for express middleware (remember, Sails is built on express) to attach properties to the req object so it may be accessed in later middleware, and eventually your controllers. What happens behind the scenes is your req object comes in with a cookie containing the session ID, and then the session middleware uses that to retrieve the actual session data from some datastore (by default, and in-memory store is used. Super fast and easy for development, but not recommended for deployment), and then attaches that to the req object.
Regarding the value of session.authenticated in your EJS, by default Sails includes req.session in res.locals (accessible in views), so that value will be whatever is stored in the session via your controller.
The browser sends over the session id which is stored on a cookie. The session object is referenced by that session id which is stored server side. The session is attached to the request (for convenience I suppose). You can read more here https://github.com/expressjs/session#compatible-session-stores
I wouldn't know what is setting session.authenticated without seeing more code.

Cross domain Sails.js + Socket.io authorization

I'm working in an application which delivers push content to a group of web applications hosted in different domains. I'm using Sails.js and Socket.io, and structured it like this:
The client script, running on each web application's client's browser, is something like:
socket.on('customEvent', function(message){
//do something with message on event trigger
}
And then, in the server, the event 'customEvent' is emitted when needed, and it works (e.g. on the onConnect event: sails.io.emit('customEvent',{message ...}).
But I'm facing a problem when it comes to handle authorization. The first approach I've tried is a cookie-based auth, as explained here (by changing the api/config/sockets.js function authorizeAttemptedSocketConnection), but it isn't a proper solution for production and it isn't supported in browsers with a more restrictive cookie policy (due to their default prohibition to third-party cookies).
My question is: how to implement a proper cross-browser and cross-domain authorization mechanism using sails.js, that can be supported in socket.io's authorization process?
======
More details:
I also tried adding a login with a well-known oauth provider (e.g. facebook), using this example as a base. I've got the Passport session, but I'm still unable to authenticate from the client script (it only works in pages hosted by my node app directly).
A JSONP request to obtain the session might be a solution, but it didn't work well in Safari. Plus I prefer the user to be authenticated in one of the web apps, rather than in my node application directly.
I believe your routes must handle CORS mate. Example:
'/auth/logout': {
controller: 'AuthController',
action: 'logout',
cors: '*'
},
Of course you can specify the list of ip your are accepting (and then replace the '*').
Worth mentionning that you must specify where socket.io has to connect to (front-end JS):
socket = io.connect(API.url);
For any common http GET/PUT/POST/DELETE, please ensure that your ajax envelope goes with the credentials (cookie). For example with angular:
$httpProvider.defaults.withCredentials = true
Let me know how it goes.

Really get all cookies with chrome.cookies.getAll?

I'm developing a chrome extension and I need to get all cookies (at least in the current CookieStore). First pass, I use
chrome.cookies.getAll({}, function (cookies) {
chrome.cookies.onChanged.addListener(function (changeInfo) {
// do stuff with added/removed cookies here ...
};
// do stuff with all the original cookies here ...
});
But now I'm thinking there may be a flaw here: the getAll call asks the browser to list all the existing cookies. The browser then calls the getAll callback with an array of these existing cookies. The extension then registers to get updates for any added/removed/changed cookies. It appears that any cookie which is added by the browser after it creates the cookies array (e.g. via active tabs), but before the addListener call executes, will be lost until updated.
Does anyone have suggestions on a better approach?
I started looking through the chrome dev tools source for examples, but it appears the Resources > Cookies table does not use this API.

How to access localStorage in node.js?

I tried searching the web for a node module that can access the client's localStorage but wasn't able to find anything. Anyone know of one?
You can use :
node-localstorage npm module to use localStorage at the nodejs server side.
var LocalStorage = require('node-localstorage').LocalStorage,
localStorage = new LocalStorage('./scratch');
If you mean html 5 localStorage, there's no such a thing since node.js is a server-side technology. Html 5 localStorage is a client side feature supported
When the page loads, send a post that queries the contents of the client's localStorage.
Found this store
// Store current user
store.set('user', { name:'Marcus' })
// Get current user
store.get('user')
// Remove current user
store.remove('user')
// Clear all keys
store.clearAll()
// Loop over all stored values
store.each(function(value, key) {
console.log(key, '==', value)
})
LocalStorage is never accessible by the server. Ever. It would be a huge security issue.
If you need to send it to a server, then you have to have a client-side JS script which retrieves it, and then sends it to the server as part of an Ajax or POST request.
Cookies work well for when you need to pass small amounts of data regularly between server and client.
Databases on your server are best if you need to store data long-term.
For Node.js you can use HandyStorage, a fast and small npm package which behaves data like a state
Here's an example:
const HandyStorage = require('handy-storage');
const storage = new HandyStorage('./store.json');
storage.setState({
name: 'Alireza',
lastname: 'Sh',
friends: [
'Jane',
'John'
],
visited: storage.state.visited || 0
})
storage.setState({
visited: storage.state.visited + 1
})
It automatically changes the JSON file, just give it a try!
In the JS file you write this:
const LocalStorage = require('node-localstorage').LocalStorage,
localStorage = new LocalStorage('./scratch');
Also you need:
open new Terminal press Control + C (don't worry it's for clear not for copy) and type you'r file.js (for ex: server.js) and than type this: npm i node-localstorage (now you all set).
Well, I think some explanations are in handy, first of all, node JS and V8 are two different things and runs on different places. Browsers uses the v8 engine to run JS, node JS runs on servers and is v8 based, but it doesn't have everything that the browser does (like the window object). So you can't access the browser local storage from your server because it's running somewhere (browsers runs on the user machine) else, I think that you want a lib that works like local storage but in your node js serve, for that we have store -> https://www.npmjs.com/package/store.
I'm From 2022 and yet there is no way we can instantly get the browser's localStorage without using fetch or ajax to communicate to the server but if you use react or veu for instance they can access it. Because they are frontend base libraries and frameworks
We can not save to localStorage on Node.js.

Resources