How to support HTTP protocol in Electron/Firebase App - javascript

I'm trying to user firebase authentication (saml) within my Electron app. I have read that Electron isn't "officially supported", however I've also encountered some threads that indicate people have gotten it to work. My issue is when using firebase.auth().signInWithRedirect (or signInWithPopup), I get the error:
code: "auth/operation-not-supported-in-this-environment"
message: "This operation is not supported in the environment this application
is running on. "location.protocol" must be http, https or chrome-extension and
web storage must be enabled."
Google turns up this tips and tricks article which suggests just using a hosted URL:
Third, OAuth requests need to have a verifiable origin, which can be whitelisted in the Firebase Console. This requires the current Electron browser window to use the http or https protocol, and not file. That means the current window contents should be loaded with browserWindow.loadURL and not browserWindow.loadFile, and the url must be an http or https url, not a file:// url. This generally requires a hosted page somewhere that gets wrapped into the Electron window.
This will probably work, as just running the app locally on the angular dev server works by simply using:
mainWindow.loadURL('http://localhost:4200');
I don't want to do this because having a hosted page lessens much of the appeal of having a native app.
I could make this work in by just having a local Node/Express instance serve the app locally using get-port to find a free port to run the app there. I haven't really seen any examples showing this. There are a few Stackoverflow questions on getting it to work, but nothing that makes me think it is an acceptable production-level solution.
Is a local Express server an acceptable way to circumvent this error, or is there currently a better solution?
Note: The package recommended in this answer is not published by Firebase and anyway doesn't look like it supports SAML auth.

I had to do something very similar but with Auth0 instead of Firebase.
What I had to do was make two Browser Windows, where the first one is strictly an authentication Browser Window while the second one is the actual main App Browser Window.
Auth0 has the same restrictions of whitelisting only http/s protocols, so in the authentication Browser window, I load the Auth0 sign in URL via localhost (it’s a hosted URL in Auth0 itself). I then take the credentials (access token and refresh token) from that redirect/Oauth process and store them locally for the time being (use Keytar, SafeStorage, FS modules, whatever; I chose Keytar).
Then my authentication Browser Window closes itself and launches the main, app Browser Window.
From here onward, I have to reference my stored access token and refresh tokens from my storage location and use those in all other calls.
So, for instance, I have some API library modules I made for myself that use Axios. So I bring the saved access token into all of my Axios calls. Works like a charm.
So, in summary: I had to use two different Browser Windows and persist credentials locally for later use in the main Browser Window.
Check out Auth0’s guide on using Electron for authentication; I think you’ll find that many concepts carry over for Firebase and other providers.

i've successfuly implemented firebase email ver in my app, it is more feasible to load .html file rather than load a page from url as users can exploit the the url by sending fake data. but with oauth it is not possible,firebase create webapp you can create a html file it should contain api keys, host url etc and host it locally in android file://android_assets/filename.html this works fine even offline i dont know properly about
electron

Related

What redirect URI should I use for an authorization call used in an Electron app?

I have a basic Electron app doing nothing special, based on sample starter projects.
For my main window, I am loading in a URL as a GET request to an API endpoing
loginWindow.loadURL('https://apiwebsite.com/api/v1.0/authorize?secret_id=my_secret&redirect_uri=<???????>')
As a part of my GET request to this API endpoint I have to send a return URI. This actually works fine, in that I can get the API to return and load the URI that I specify. However I do not know what URI to specify to get this to come back to somewhere within my app where I can read the response and proceed.
I am used to web development but Electron is new to me. I do not follow how I can submit a return URI in this instance. What would be it be? Would it change for local development vs a packaged application?
Is there a better way to do this?
OAUTH FOR DESKTOP APPS
OAuth for desktop apps recommends these 2 key behaviours:
Login via the system browser so that your app never sees the user credential
Use Authorization Code Flow (PKCE) since your app is a public client
This typically leads to one of these solutions:
Loopback based redirect URI such as http://127.0.0.1:8000/callback
Private URI scheme based redirect URI such as x-mycompany-desktopapp:/callback
As you are finding, a standard HTTP based internet redirect URL will not work for a desktop app unless you use older (deprecated) web view solutions.
RESOURCES OF MINE
It is tricky flow to implement, though my blog has a couple of Electron code samples that you can easily run from your local PC to see what both solutions look like:
Initial Desktop Code Sample, using the Loopback Solution
Final Desktop Code Sample, using the Private URI Scheme Solution
My samples are quite deep, but hopefully some of this is useful for your own solution ...

How to proxy all XMLHttpRequest in a web browser?

I'm using Google Firebase, and unfortunately, Google Firebase put some countries under sanctions which means they must use a proxy (or VPN) to access the website.
Is there any way I can set a proxy setting for each client request that they can freely access Firebase without a VPN?
I know there are options for Node.js, but I'm looking for a web browser solution. Firefox has this proxy settings, and Google Chrome also has some options for extension developers, but I need a solution that works just in a web page, and it means when a user comes to my website, he/she does not need to set a proxy to access Firebase.
Example: when a user comes to my website from (for example) Syria or Sudan, they don't need to set VPN for their browser, because I have done some proxy configuration in my website
Short answer: You can't do it website-only.
Longer answer / explanation:
I know there are options for Node.js,
Good... that could work. Deploy your own Node.js server on Heroku or the like, which proxies requests to Firebase.
but I'm looking for a web browser solution. Firefox has this proxy settings, and Google Chrome also has some options for extension developers, but
This could work too, but as I'm sure you've considered... that would rely on the end-users installing those extensions before attempting to visit your site.
I need a solution that works just in a web page,
Nope. Not possible. The Google servers will not respond to any request coming from a sanctioned country. If a request comes from a disallowed country, the Firebase servers won't respond with your website - instead they respond with a 403. Firebase won't send the website. Your website won't be sent to the client. It doesn't matter what your website contains, it will never be sent to those end users in the first place.
Even if you host the site elsewhere, and just use the Firebase database, it still won't work - for the same reasons. When the Firebase servers receive the request from a browser running in a sanctioned country, they respond with 403.
The question then becomes: How to make the request appear to come from outside the sanctioned country, from the website only?
You can't, not when you only control the website itself. That part of the request/response cycle is, for end-user protection purposes, handled by the browser. Browsers do not expose that functionality to webpages.
If you want to handle everything for your users, without them needing a VPN (desktop, or browser), your only choice will be to send the request to a different non-Google server (such as a Node.js server you host on Heroku or the like), which then makes the request to Firebase on their behalf, gets the response, and responds back to the client. That way, to the Firebase servers, it looks like the request is coming from X* location.
*X: Where ever the Heroku server is running.

HTTPS on localhost for OAuth for a desktop application

I am creating a desktop application that using Spotify's oauth api. I am using the implicit grant flow described here: https://developer.spotify.com/web-api/authorization-guide/#implicit_grant_flow
My idea is to have an "Authenticate" button, that you click and it opens your browser. You login/approve the connection with Spotify. Then it sends you to a redirect url.
I want to set this redirect url to 127.0.0.1:58212 or some port on the loopback device.
My question is, should I use https for this?
I am leaning towards yes. One because the access token needs to be secure, and I believe other users on the system could potentially read the message when it is sent, and two because in the time it took the user to log in, someone could have taken over the port.
So I want SSL for encryption of the message, and I want to ensure I am actually talking to my app.
How do I generate certificates in this situation? I think each instance of the application needs to have its own certificate, and I need to somehow inform the computer to trust that certificate during the lifetime of the application.
I could also generate the certificate during installation, and do some step during installation that makes the system trust that certificate.
Am I thinking about this the correct way, or am I going about this all wrong?
I am using electron and express in JavaScript to write my application.
Thanks for any advice.
The best way to securely use Oauth with installed applications such as desktop applications is to use the Oauth 2 flow for installed applications. But this option would have to be implemented by the service provider. Google provides for this option.
https://developers.google.com/api-client-library/python/auth/installed-app
Unfortunately, many services do not implement OAuth2.
To use Oauth 1.0 with installed applications, instead of returning to a callback_url, the service provider displays the auth code to the user which the user can then copy and paste to the desktop application. Check out Trello Ouath integration which allows for this.
The Web Api flow that you are trying to achieve will not work in the case of desktop apps. The redirect uri 127.0.0.1:port is your local uri. The service provider will need, at the very least, your public ip to redirect the flow back to your system.
AFAIK, for a Desktop or a native app it is much better to implement the Oauth authorization code flow. The implicit grant is intended to be used on a device browser and not on a Web View.
If your app uses a Web Service to connect, your Web Service needs a redirect URL that uses https. Luckily most hosting platforms like Heroku provide this to you for free (otherwise you need to buy an SSL certificate which might be a lot of work).
On the authorization code flow, a token doesn't need to see the client, it is all stored in the backend.
Most services allow you to test on localhost with http.
I wrote a tutorial that could give you some guidance on the flow.

How to test Pinterest SDK locally?

I'm testing out the Pinterest SDK on my local machine. The problem is, I need a secure server in order to test the API (they only allow Redirect URIs with a HTTPS prefix).
Every time I try to login to the Pinterest application it throws the error:
{"status": "failure", "message": "You are not permitted to access that resource.", "code": 7, "data": "The provided redirect_uri http://localhost:3000/ does not match any of the registered redirect URIs."}
Is there any way I can test via HTTPS locally?
If you are using Create React App you can start the development server in HTTPS, see https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#using-https-in-development
You can't. Pinterest demands that you have https link.
I tried using ngrok to convert my localhost link to an https link for testing. But it was throwing some errors, so skipped it. You can try it out though
But if you wish to have a temporary setup to work with the APIs, lets say to write down functions to process information you get from APIs, which was my requirement, then you can follow what I did. May not be the best option, but I could get my job done.
I hosted a basic app on firebase. Firebase provides some sample apps which you can use as base app if you want.
Just get the link of the hosted app and add it in your app page in Pinterest.

Secure Website in Chrome Kiosk Mode

I have a little Node app on heroku. It's embedded in a Chrome kiosk app.
I would like the app to only be accessible on the Chromebooks that have it installed in kiosk mode.
I've tried HTTP authentication, but after I put in my password and username, the app never loads. However this is also not ideal in the first place, as I would like to avoid requiring a password on the Chromebook.
Any ideas?
If you provision the chromebooks yourself, you might be able to use TLS client authentication.
You would install an ssl certificate on the chromebook once which you can then use to authenticate to the web server. A nodejs example can be found here http://nategood.com/nodejs-ssl-client-cert-auth-api-rest
There is also a passport.js module for this https://github.com/ripjar/passport-client-cert
In theory a user can install the certificate on his own, he would get a message asking him to confirm the installation of the certificate, hit okay and that's it.
But be aware, that the certificate can easily be extracted from the chromebook via the settings.
If I understand correctly, you want to make your website only accessible from the chromebooks you configured. Please clarify if this is not what you meant.
Then you can have a landing page (can require authentication) that generates a random token for your chromebooks on first run only. Store this token in a cookie or local storage, and send it every time the app runs to verify on the server.

Categories