This isn't a complete project - just a part of one, but I thought it worth sharing, both because it might inspire others and people might spot a security flaw I've missed.
Background: the site I run is a social network, and we also have apps built in B4X, which talk to the system via an API built around JSON data posted to an endpoint encrypted using TLS. I often have problems with users who've forgotten passwords - especially if they tend to use the app. When the app is set up, it asks for permission to use your account, and once that's done, it doesn't ask for anything more (a bit like oAuth, but less convoluted). You can, if you want, tell the app to request a PIN or biometric id when it starts.
So, since people tend to carry their phones, on which they can easily authorise themselves in a number of ways, and forget passwords, I wanted to find a way people could sign in to the site without a password, while still maintaining security. This is the result.
The user goes to the site, and in the login box, they just type their email address, and click the 'Login with the app' button. A notification is sent to their mobile device, listing details about the login request, and a progress update is displayed in the browser. If the request is confirmed on the mobile device, then the login is completed in the browser.
How it works:
1. On the website, when the user's email address is entered, a temporary session id is created and stored in the database, along with a status.
2. A Firebase cloud message is sent to the user's topic, indicating that there's a login request. This may go to numerous devices, so contains no secret data
3. The user's app authenticates itself with the API, and requests details of the login attempt.
4. Geolocation (from the IP address) and browser info are returned, together with the temporary session id, encrypted with the member's public key
5. The app presents the information and asks the user to allow or deny the request
6. The temporary session id is decrypted by the app, and then re-encrypted using the server's public key, and returned alongside the decision on the login
7. The API server decrypts the received session id, and if there's a temporary session with that it, for the member associated with the app, then the status in the temporary session table is updated to allow login
Meanwhile, the login page that's displayed in the user's browser refreshes every few seconds; as it does the database is queried for the temporary session key and its status, so the user will see messages like "Attempting to contact your mobile device" or the one shown in the screenshot, with browser and IP information. If there's no response within three minutes, the status is changed to "timeout"
However, if the page reloads and the status is set to "authorised" in the database, then the normal session startup procedures for the website are run, and the user's directed to their post-login landing page.
I'm going to allow only one device per user to be configured to work this way, but I think it'll make it simple for a lot of people to log on without remembering passwords. I may perhaps restrict the functionality to those who have put a PIN or biometrics on their app startup, too.
All the communications happen over TLS, nothing is sent via a GET request that could hang around in logs anywhere, and the key bit of data, the temporary session id, is always encrypted for transfer.
Any feedback is welcome; I can post some of the code snippets too, I guess.
Background: the site I run is a social network, and we also have apps built in B4X, which talk to the system via an API built around JSON data posted to an endpoint encrypted using TLS. I often have problems with users who've forgotten passwords - especially if they tend to use the app. When the app is set up, it asks for permission to use your account, and once that's done, it doesn't ask for anything more (a bit like oAuth, but less convoluted). You can, if you want, tell the app to request a PIN or biometric id when it starts.
So, since people tend to carry their phones, on which they can easily authorise themselves in a number of ways, and forget passwords, I wanted to find a way people could sign in to the site without a password, while still maintaining security. This is the result.
The user goes to the site, and in the login box, they just type their email address, and click the 'Login with the app' button. A notification is sent to their mobile device, listing details about the login request, and a progress update is displayed in the browser. If the request is confirmed on the mobile device, then the login is completed in the browser.
How it works:
1. On the website, when the user's email address is entered, a temporary session id is created and stored in the database, along with a status.
2. A Firebase cloud message is sent to the user's topic, indicating that there's a login request. This may go to numerous devices, so contains no secret data
3. The user's app authenticates itself with the API, and requests details of the login attempt.
4. Geolocation (from the IP address) and browser info are returned, together with the temporary session id, encrypted with the member's public key
5. The app presents the information and asks the user to allow or deny the request
6. The temporary session id is decrypted by the app, and then re-encrypted using the server's public key, and returned alongside the decision on the login
7. The API server decrypts the received session id, and if there's a temporary session with that it, for the member associated with the app, then the status in the temporary session table is updated to allow login
Meanwhile, the login page that's displayed in the user's browser refreshes every few seconds; as it does the database is queried for the temporary session key and its status, so the user will see messages like "Attempting to contact your mobile device" or the one shown in the screenshot, with browser and IP information. If there's no response within three minutes, the status is changed to "timeout"
However, if the page reloads and the status is set to "authorised" in the database, then the normal session startup procedures for the website are run, and the user's directed to their post-login landing page.
I'm going to allow only one device per user to be configured to work this way, but I think it'll make it simple for a lot of people to log on without remembering passwords. I may perhaps restrict the functionality to those who have put a PIN or biometrics on their app startup, too.
All the communications happen over TLS, nothing is sent via a GET request that could hang around in logs anywhere, and the key bit of data, the temporary session id, is always encrypted for transfer.
Any feedback is welcome; I can post some of the code snippets too, I guess.