{"id":49247334,"url":"https://github.com/zlenner/device-auth","last_synced_at":"2026-04-24T22:40:54.702Z","repository":{"id":183402448,"uuid":"670109253","full_name":"zlenner/device-auth","owner":"zlenner","description":"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.","archived":false,"fork":false,"pushed_at":"2023-07-26T11:04:49.000Z","size":738,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-09T09:35:30.940Z","etag":null,"topics":["auth","authentication","javascript","webauthn"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zlenner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-24T10:10:20.000Z","updated_at":"2024-11-22T04:24:51.000Z","dependencies_parsed_at":"2024-10-30T19:04:12.430Z","dependency_job_id":"50341397-caf7-4244-b16d-8d70d3223643","html_url":"https://github.com/zlenner/device-auth","commit_stats":{"total_commits":48,"total_committers":1,"mean_commits":48.0,"dds":0.0,"last_synced_commit":"c05ae776344caf304ebc446e888676139eefe886"},"previous_names":["zlenner/device-auth"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zlenner/device-auth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlenner%2Fdevice-auth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlenner%2Fdevice-auth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlenner%2Fdevice-auth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlenner%2Fdevice-auth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zlenner","download_url":"https://codeload.github.com/zlenner/device-auth/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlenner%2Fdevice-auth/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32243799,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-24T13:21:15.438Z","status":"ssl_error","status_checked_at":"2026-04-24T13:21:15.005Z","response_time":64,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth","authentication","javascript","webauthn"],"created_at":"2026-04-24T22:40:54.199Z","updated_at":"2026-04-24T22:40:54.697Z","avatar_url":"https://github.com/zlenner.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# device-auth\n\nDevice-Auth is a simple library that allows you to authenticate users on both the browser and server side.\n\n## Demo\n\nhttps://github.com/zlenner/device-auth/assets/119705166/b8bba30f-ee0e-4a87-b2c7-81f255142b34\n\n[Here!](https://zlenner.github.io/device-auth/)\n\nThis demo uses an in-browser mock server to complete the sign-in, and stores the returned access token in your localStorage.\n\n## Installation\n\nTo install the library, run the following command:\n\n```\nnpm install device-auth\n```\n\n## Quickstart\n\n### (1) Issue a challenge in the server.\n\n**BROWSER:**\n```javascript\nconst challenge = await fetchJsonFromServer.get(\"/issue_challenge\")\n```\n\n**SERVER:**\nCreate one instance of DeviceAuth per server, and a route to issue a challenge.\n\n```javascript\nimport { server } from \"device-auth\"\n\ndevice_auth = new server.DeviceAuth()\n\n// Whatever your app is, express fastify etc.\napp.get(\"/issue_challenge\", async () =\u003e {\n  return device_auth.issue_challenge()\n})\n```\n\n### (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.\n\n**BROWSER:**\n```javascript\nimport { browser } from \"device-auth\"\n\nconst payload = await browser.authenticate_or_register(challenge)\n```\n\nNOTE: 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.\n\n### (3) Send the payload to the server to complete the sign-in and get a token back.\n\n**BROWSER:**\n\n```javascript\nconst token = await fetchJsonFromServer.post(\"/verify\", payload)\n```\n\n**SERVER:**\n\nIf the `payload.type` == `authenticate`, we'll fetch the credential from our database and use the `verify_authentication` method.\n\nIf the `payload.type` == `register`, we'll use the `verify_registration` method.\n\nEither way, the server should respond with a token if the authentication/registration was successful.\n\n```javascript\nconst access_tokens: string[] = []\n\napp.post(\"/verify\", async (request) =\u003e {\n  const payload = request.body\n  if (payload.type == \"authenticate\") {\n    const credential = await database.get(payload.credential_id)\n    await device_auth.verify_authentication(payload, credential)\n  \n  } else if (payload.type == \"register\") {\n    await device_auth.verify_registration(payload)\n    await database.store(payload.credential_id, payload.credential)\n  }\n  // If the code didn't throw an error by now, sign-in succeeded!\n\n  // Generate a token and return it to the client.\n  // Use something more secure than this on your app!\n  const token = Math.random().toString(36)\n  access_tokens.push(token)\n\n  return token\n})\n```\n\n### (4) You're a member of the app (club)! You now have access to all the secrets of the club :D\n\n**BROWSER:**\n\n```javascript\nconst secret_thing = await fetchJsonFromServer.post(\"/get-secret-thing\", { token })\n```\n\n**SERVER:**\n\n```javascript\napp.post(\"/get-secret-thing\", async (request) =\u003e {\n  if (!access_tokens.includes(request.body.token)) {\n    throw new Error(\"You don't have access!!!\")\n  }\n  // Woosh, this request was made by a member of the club.\n\n  return \"Psst, the secret is ____________\"\n})\n```\n\n## Full documentation\n\nThe Quickstart is what most people will need. There are more functions available which you can check out through the typescript auto-complete.\n\n## Known issues\n1. An attacker can issue infinite challenges until the memory overflows and the app crashes. Can be somewhat mitigated with IP rate-limiting.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzlenner%2Fdevice-auth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzlenner%2Fdevice-auth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzlenner%2Fdevice-auth/lists"}