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.
Related
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
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.
My company is looking at using card based certificates (like CACs) for authentication on a web site; instead of the user entering a username and password this information would be extracted from the certificate. How does one go about programming the front end to pass the certificate on to the webserver? I've been looking for specific directions but wind up with everything but that. The over all idea is to hook into something like an LDAP for authentication eventually, but the browser part is completely eluding me.
You don't really have to do much in the way of the client side stuff. For a website, the browser handles it for you. You just have to setup your server to require a client certificate and the browser will handle it. Under Apache, after setting up the SSL certificate, this is as simple as setting SSLVerifyClient required (manual) in the apache configuration. Your site will then require a client certificate for access. You can also set SSLVerifyClient to optional which allows someone to click "Cancel" when prompted to select a certificate and the site will still load, but is missing the environment variables (see below).
If you are using smart cards, you might need a driver for the smart card reader to prompt the user for a pin to query the card, but it isn't something you need to handle. In my experience (with CAC cards), both Internet Explorer and Firefox use a third party software (we use ActiveIdentity) to ask for the user's pin (Firefox needs to be setup to use a "Security Device", but it is simple) and Chrome already has built in support for the smart cards without needing a separate program. It is also possible to install the certificate in the browser, but I haven't worked with that.
As for validating the user, in Apache, once the SSL handshake stuff has been completed by the browser and server, in PHP there are several environment variables that are available (you can see them on a phpinfo() page or if you print_r($_SERVER). They are all SSL_* and include stuff like the domain or common name). This can differ based on what information was supplied from the client. We just found one that held a unique id for the card $_SERVER['SSL_CLIENT_S_DN_CN'] and store that with each account. Then we can use that id to query for the account for creating a validated user session.
SSL client certificates are presented in the SSL handshake, which is done in the lower layers and is therefore transparent to the frontend (browser handles it internally). The web server needs to be configured to accept or require the client certificates so they are requested in the SSL handshake.
The client certificate is then validated by the web server and you can then access the client's identity typically via some API, depending on the server/platform.
EDIT:
Here's a guide for nginx/PHP: http://nategood.com/client-side-certificate-authentication-in-ngi
I want to test service workers but I have a virtual host setup and I can't seem to be able to enable https on localhost.
How can I whitelist my local virtual host url to test service workers
whenever I try and register for the service worker on the localhost? Chrome says https is required to enable service worker. How can I get past this restriction at least for local testing.
In general, you need to serve both your page and your service worker script via HTTPS in order to use service workers. The rationale is described at Prefer Secure Origins For Powerful New Features.
There's an exception to the HTTPS requirement in place to facilitate local development: if you access your page and service worker script via http://localhost[:port], or via http://127.x.y.z[:port], then service workers should be enabled without any further actions.
In recent versions of Chrome, you can work around this requirement duriing local development via chrome://flags/#unsafely-treat-insecure-origin-as-secure, as explained in this answer.
Firefox offers similar functionality, via the devtools.serviceWorkers.testing.enabled setting.
Please note that this functionality is only meant to facilitate testing that wouldn't otherwise be able to take place, and you should always plan on using HTTPS when serving the production version of your site. Don't ask real users to go through the steps of enabling those flags!
If you want to debug a plugged-in mobile device's service worker for a real behavior testing of a progressive web app, the ssl chrome start options do not help and you definitely do not need to buy certificates.
#chris-ruppel mentioned installing proxy software, but there is actually an easier way using port forwarding:
Assuming you connect and debug your device using Chrome:
In the Chrome Dev Tools "Remote devices" open "Settings" and add a "Port forwarding" rule.
If your localhost setup is running on localhost:80,
just add a rule "Device port 8080" (can be any unpriviliged port > 1024)
and local address "localhost:80" (or mytestserver.sometestdomainwithoutssl.company:8181 or whatever)
After you did that, you can call the URL "http://localhost:8080" on your mobile device and it will be answered by the "localhost:80" on your actual PC/test server. Works perfectly with service workers as if it were your local machine running on your mobile.
Works also for multiple port forwardings and different target domains as long as you remember to use unprivileged ports on your mobile device. See screenshot:
Source of this info is the google remote devices documentation: https://developers.google.com/web/tools/chrome-devtools/remote-debugging/local-server
(but as of Apr 2017 it is not very clear to read this simple answer out of it)
I often want to debug and test on a real device. One method I've come up with involves routing the phone's network traffic through Charles Proxy during local development. Unlike all the Chrome-specific solutions, this works with any browser on your phone.
Run Charles on my laptop (which also serves my website with the Service Worker). Once Charles is running, note the IP/port for Step 2.
Configure the mobile device to use my laptop as a proxy.
For Android just tap and hold on your WiFi in settings > Modify network > Advanced Settings > Proxy. Use Manual to set the IP/port.
For iOS click the (i) icon > HTTP Proxy section. Select Manual, then set the IP/port.
Visiting localhost on my mobile device now allows the Service Worker to be registered and tested.
The easiest way to test pwa, in my case, was using ngrok.
https://ngrok.com/download log in, get ur token and set it!
When you run ./ngrok http {your server port} make sure that you use https which will be shown in the terminal after you run this command above.
You could use https://surge.sh too, it is for host a static webpage, if you visit here: https://surge.sh/help/securing-your-custom-domain-with-ssl
will be able to see how to set up a ssl certificate
I used ngrok to tunnel the local IP (it is really not that because it is on Google Colab) to a public one.
Going to the ngrok console I can see all the tunnels created. I created just one tunnel for localhost:port but here there are 2, one for HTTP and other for HTTPS (isn't that nice?).
If I go to the https address of my Web App, on the console I see
But if I go to the http address, on the console I get
Q: Can you work with service workers that need HTTPs through tunnels to a remote machine?
A: Apparently yes!
The code behind that registration is (important to know where it fails):
// Here we register the SERVICE WORKER
IndexController.prototype._registerServiceWorker = function() {
console.log("1.Starting SW function.");
if (!navigator.serviceWorker) {
console.log("2.Browser is NOT compatible with SW or something is not working.");
return; }
console.log("2.Browser is compatible with SW.");
navigator.serviceWorker.register('/sw.js').then(function() {
console.log('3.Registration worked!');
}).catch(function() {
console.log('3.Registration failed!');
});
};
And to make it more complicated, my web App using Service Workers is running inside Colab (Google Colab). The web App is running on Node.js inside Colab.
If you are working from localhost it should be easier for you, because the https requirement is not enforced when connecting to localhost (according to theory). [A] and [B]
That is not the same that the browser will be nice with your App just because it runs on localhost.
Note: My experiment above..
Firefox: worked with and without the settings below.
Chrome: Without adding the urls to the whitelist and restartting I got
Going to https web app I got:
IndexController.js:49 Mixed Content: The page at 'https://0a4e1e0095b0.ngrok.io/' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://0a4e1e0095b0.ngrok.io/updates?since=1602934673264&'. This request has been blocked; this endpoint must be available over WSS.
IndexController._openSocket # IndexController.js:49
IndexController # IndexController.js:10
(anonymous) # index.js:16
loadScripts # loadScripts.js:5
46.../utils/loadScripts # index.js:15
s # _prelude.js:1
e # _prelude.js:1
(anonymous) # _prelude.js:1
IndexController.js:49 Uncaught DOMException: Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.
at IndexController._openSocket (https://0a4e1e0095b0.ngrok.io/js/main.js:2251:12)
Going to http web app I got:
Navigated to http://0a4e1e0095b0.ngrok.io/
IndexController.js:17 1.Starting SW function.
IndexController.js:19 2.Browser is NOT compatible with SW or something is not working.
If you are not on localhost AND can't use https, then you may need to change these settings on your browser.
Some people already explained this but here it goes again.
Chrome:
Go to chrome://flags/#unsafely-treat-insecure-origin-as-secure
Add the urls you want to whitelist.
Restart chrome
Note that this will restart all Chrome windows. This is not a solution for me because my tunnels change name every time they are created and I can't be restarting a bunch of windows every time.
Firefox / Waterfox
Open Developer Tools
Open settings
Mark "Enable service workers over HTTP (when toolbox is open)"
Firefox/Waterfox
You probably don't need to do the changes below, but I did (my browser may be a bit old). More info here.
In about:config
I enabled
dom.serviceWorkers.testing.enabled
dom.serviceWorkers.enabled
I highly recommend looking at this https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers and related pages on that same site.
If someone is interested in the ngrok setup, it is very simple (python version).
# Install pyngrok python package on your Google Colab Session
!pip install pyngrok
# Set up your ngrok Authtoken (requires free registration)
!ngrok authtoken YOUR_TOKEN_HERE
# Invoke ngrok from Python and start tunneling/connecting
from pyngrok import ngrok
# Open a HTTP tunnel on the default port 80 if not specified
ngrok_tunnel = ngrok.connect('8888')
# You can print it, or go to the ngrok console on https://dashboard.ngrok.com/status/tunnels
print (ngrok_tunnel.public_url)
If you want to test service workers on a client device that cannot run a web server on localhost, the general technique is as follows:
Give your server a hostname.
Give this hostname a certificate.
Make IPs trust the CA that issued this certificate.
But this is easier said than done. In a November 2016 AMA on Reddit, a Let's Encrypt representative acknowledged that HTTPS on a private LAN "is a really tough question, and I think no one has come up with a satisfactory answer so far."
Common ways to give your computer a hostname involve giving it a stable internal IP address, not one that changes daily or every time you power-cycle your Internet gateway appliance. You'll need to configure the DHCP server on your network, usually that in your gateway, to set up a "reservation" that associates a particular private address (usualy within 10/8 or 192.168/16) with the MAC address of your development workstation's Ethernet card. For this, read the manual of your gateway.
Now that your development workstation has a stable IP address, there's a time/money tradeoff. If you're willing to learn advanced DNS and OpenSSL usage and install a root certificate on all devices with which you plan to test:
Run an internal DNS server on your network. This could be on your gateway or on your development workstation.
Configure your DNS server to be authoritative for some made-up TLD and recursive for other TLDs.
Give a stable name to your development workstation's private IP address. This gives it an internal name.
Configure your DHCP server to give the address of this DNS server to other devices obtaining leases.
On your development workstation, use OpenSSL to generate keypairs for a private certificate authority and the web server.
Using OpenSSL, issue a root certificate for the CA and a certificate for the web server's internal name.
Configure HTTPS in the web server on your development workstation using this certificate.
Install the CA's root certificate as a trusted root certificate on all devices.
On all devices, access this internal name.
If you cannot add a root certificate or control local DNS, such as if you plan to test with devices owned by others (BYOD) or with more locked-down browsers that do not allow users to add trusted root certificates, such as those in major video game consoles, you'll need a fully-qualified domain name (FQDN):
Buy a domain from a registrar that offers DNS with an API. This could be directly within a TLD or from one of the dynamic DNS providers that has made it onto the Public Suffix List. (Non-PSL dynamic DNS providers are unacceptable because of rate limits imposed by Let's Encrypt.)
In this domain's zone file, point an A record at your development workstation's private IP address. This gives your development workstation a FQDN.
Use Dehydrated, an ACME client that supports the dns-01 challenge, to obtain a certificate for this FQDN from the Let's Encrypt certificate authority.
Configure HTTPS in the web server on your development workstation using this certificate.
On all devices, access this name.
As Jeff mentioned in the first response, you do not need https at the localhost level to test Service Workers. Service workers will register and work just fine as long as you access the localhost domain -- without HTTPS.
Once you have your application tested on localhost and you want to see how it works with https for real, the simplest approach would be to upload your app to GitHub. You can create a public domain for free (and with HTTPS!).
Here are the instructions: https://pages.github.com/
I think the easiest way to test service worker is to find a free hosting provider.
nowadays, there many sites that provide free hosting. you can easily host your app on this free servers.
I mostly use heroku and netlify. this are free and easy to use.
For mobile testing with Android over the network with plain HTTP, a simple solution is to install Termux on your phone, then use socat to port-forward from a local port to your development host:
socat tcp-l:8000,fork,reuseaddr tcp:192.168.1.170:8000
This will run in the background while the terminal is running. Then in Chrome you can connect over plain HTTP to http://127.0.0.1:8000.
Works great over the local network and no certs, apps or services needed.
So I'm getting into working with node.js and socket.io to make real-time web games, but I'm running into some obstacles.
I've already figured out how to install node.js and socket.io on my computer, and I can run basic servers and open them through http://localhost:8888/.
But now what I don't understand, and there doesn't seem to be anything on the web that explains this, is how to get this onto a website. Obviously, someone else on the internet that enters that same URL isn't going to see the same thing as what's on my screen. How do I get this onto a webpage so that anyone that visits that URL accesses the server?
I tried opening the port and then using http://<my external IP>:8888 but that doesn't work. Some sources seem to say that I need to install something on the website, but I installed node.js on my computer through command prompt, so I don't understand how that would work on a website. I found instructions for Linux, but I'm running Windows.
What you need is a:
web server - to host your game. You can, for instance, rent an EC2 instance from Amazon and install there all software required (Node.js, database, ...) or go with PaaS (Platform as a Service) solution like Nodejitsu or Heroku where you'll be given Node.js out of the box.
domain - to register a human-readable name for your web serwer (like. www.my-game.com). Normally, once you get your server, it'll have some IP address assigned to it. Domain name is an alias for it, easier to type and remember. Similar to, as in your case, localhost is just an alias for an IP 127.0.0.1 (special address meaning local system).
Of course, another solution would be to host app on your local PC and set up your router to forward traffic from it's external IP to your PC (assuming your ISP assigned you public IP). But then you'll have to worry about your PC, router and internet link being always online. And it'd be way slower than when going with external, dedicated hosting.