https://github.com/zlenner/device-auth
Device-Auth is a shower-thought turned library that allows you to authenticate users with NO email, NO passwords, and NO 3rd-party accounts. Just your device.
https://github.com/zlenner/device-auth
auth authentication javascript webauthn
Last synced: about 2 months ago
JSON representation
Device-Auth is a shower-thought turned library that allows you to authenticate users with NO email, NO passwords, and NO 3rd-party accounts. Just your device.
- Host: GitHub
- URL: https://github.com/zlenner/device-auth
- Owner: zlenner
- Created: 2023-07-24T10:10:20.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2023-07-26T11:04:49.000Z (almost 3 years ago)
- Last Synced: 2026-01-09T09:35:30.940Z (5 months ago)
- Topics: auth, authentication, javascript, webauthn
- Language: TypeScript
- Homepage:
- Size: 721 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# device-auth
Device-Auth is a simple library that allows you to authenticate users on both the browser and server side.
## Demo
https://github.com/zlenner/device-auth/assets/119705166/b8bba30f-ee0e-4a87-b2c7-81f255142b34
[Here!](https://zlenner.github.io/device-auth/)
This demo uses an in-browser mock server to complete the sign-in, and stores the returned access token in your localStorage.
## Installation
To install the library, run the following command:
```
npm install device-auth
```
## Quickstart
### (1) Issue a challenge in the server.
**BROWSER:**
```javascript
const challenge = await fetchJsonFromServer.get("/issue_challenge")
```
**SERVER:**
Create one instance of DeviceAuth per server, and a route to issue a challenge.
```javascript
import { server } from "device-auth"
device_auth = new server.DeviceAuth()
// Whatever your app is, express fastify etc.
app.get("/issue_challenge", async () => {
return device_auth.issue_challenge()
})
```
### (2) Use the `authenticate_or_register` function, which takes a challenge as an argument and registers a user. If already registered, the function will authenticate the user instead.
**BROWSER:**
```javascript
import { browser } from "device-auth"
const payload = await browser.authenticate_or_register(challenge)
```
NOTE: On incognito, or if the user has cleared their localStorage, this will register a new user, but the previous user will still be available for sign-in after a new user has been registered.
### (3) Send the payload to the server to complete the sign-in and get a token back.
**BROWSER:**
```javascript
const token = await fetchJsonFromServer.post("/verify", payload)
```
**SERVER:**
If the `payload.type` == `authenticate`, we'll fetch the credential from our database and use the `verify_authentication` method.
If the `payload.type` == `register`, we'll use the `verify_registration` method.
Either way, the server should respond with a token if the authentication/registration was successful.
```javascript
const access_tokens: string[] = []
app.post("/verify", async (request) => {
const payload = request.body
if (payload.type == "authenticate") {
const credential = await database.get(payload.credential_id)
await device_auth.verify_authentication(payload, credential)
} else if (payload.type == "register") {
await device_auth.verify_registration(payload)
await database.store(payload.credential_id, payload.credential)
}
// If the code didn't throw an error by now, sign-in succeeded!
// Generate a token and return it to the client.
// Use something more secure than this on your app!
const token = Math.random().toString(36)
access_tokens.push(token)
return token
})
```
### (4) You're a member of the app (club)! You now have access to all the secrets of the club :D
**BROWSER:**
```javascript
const secret_thing = await fetchJsonFromServer.post("/get-secret-thing", { token })
```
**SERVER:**
```javascript
app.post("/get-secret-thing", async (request) => {
if (!access_tokens.includes(request.body.token)) {
throw new Error("You don't have access!!!")
}
// Woosh, this request was made by a member of the club.
return "Psst, the secret is ____________"
})
```
## Full documentation
The Quickstart is what most people will need. There are more functions available which you can check out through the typescript auto-complete.
## Known issues
1. An attacker can issue infinite challenges until the memory overflows and the app crashes. Can be somewhat mitigated with IP rate-limiting.