{"id":18561410,"url":"https://github.com/apostrophecms/login-totp","last_synced_at":"2026-02-21T08:37:15.800Z","repository":{"id":44612012,"uuid":"451963097","full_name":"apostrophecms/login-totp","owner":"apostrophecms","description":null,"archived":false,"fork":false,"pushed_at":"2025-04-02T12:24:19.000Z","size":103,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-22T18:48:39.472Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/apostrophecms.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","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,"zenodo":null}},"created_at":"2022-01-25T16:52:00.000Z","updated_at":"2025-04-02T12:24:22.000Z","dependencies_parsed_at":"2024-02-02T16:28:52.366Z","dependency_job_id":"29032972-b7e7-4f38-98c2-b65faf0aaa29","html_url":"https://github.com/apostrophecms/login-totp","commit_stats":{"total_commits":57,"total_committers":4,"mean_commits":14.25,"dds":0.4035087719298246,"last_synced_commit":"408f1ace6f0b05dc25dcfb9b01d60501f5bd99c2"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/apostrophecms/login-totp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostrophecms%2Flogin-totp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostrophecms%2Flogin-totp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostrophecms%2Flogin-totp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostrophecms%2Flogin-totp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apostrophecms","download_url":"https://codeload.github.com/apostrophecms/login-totp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostrophecms%2Flogin-totp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29677638,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T06:23:40.028Z","status":"ssl_error","status_checked_at":"2026-02-21T06:23:39.222Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":[],"created_at":"2024-11-06T22:06:46.449Z","updated_at":"2026-02-21T08:37:15.784Z","avatar_url":"https://github.com/apostrophecms.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/apostrophecms/apostrophe/main/logo.svg\" alt=\"ApostropheCMS logo\" width=\"80\" height=\"80\"\u003e\n\n  \u003ch1\u003eApostrophe TOTP Login Verification\u003c/h1\u003e\n  \u003cp\u003e\n    \u003ca aria-label=\"Apostrophe logo\" href=\"https://v3.docs.apostrophecms.org\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/MADE%20FOR%20ApostropheCMS-000000.svg?style=for-the-badge\u0026logo=Apostrophe\u0026labelColor=6516dd\"\u003e\n    \u003c/a\u003e\n    \u003ca aria-label=\"Test status\" href=\"https://github.com/apostrophecms/login-totp/actions\"\u003e\n      \u003cimg alt=\"GitHub Workflow Status (branch)\" src=\"https://img.shields.io/github/workflow/status/apostrophecms/login-totp/Tests/main?label=Tests\u0026labelColor=000000\u0026style=for-the-badge\"\u003e\n    \u003c/a\u003e\n    \u003ca aria-label=\"Join the community on Discord\" href=\"http://chat.apostrophecms.org\"\u003e\n      \u003cimg alt=\"\" src=\"https://img.shields.io/discord/517772094482677790?color=5865f2\u0026label=Join%20the%20Discord\u0026logo=discord\u0026logoColor=fff\u0026labelColor=000\u0026style=for-the-badge\u0026logoWidth=20\"\u003e\n    \u003c/a\u003e\n    \u003ca aria-label=\"License\" href=\"https://github.com/apostrophecms/login-totp/blob/main/LICENSE.md\"\u003e\n      \u003cimg alt=\"\" src=\"https://img.shields.io/static/v1?style=for-the-badge\u0026labelColor=000000\u0026label=License\u0026message=MIT\u0026color=3DA639\"\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\nThis login verification module adds a [TOTP (Time-based One-Time Password)](https://en.wikipedia.org/wiki/Time-based_one-time_password) check when any user logs into the site, compatible with Google Authenticator or any TOTP app.\nWhen activated, it will ask unregistered users to add a token to their app through a QR code. Once done, it will ask users to enter the code provided by their app after the initial login step.\n\n## Installation\n\nTo install the module, use the command line to run this command in an Apostrophe project's root directory:\n\n```\nnpm install @apostrophecms/login-totp\n```\n\n## Usage\n\nInstantiate the TOTP login module in the `app.js` file:\n\n```javascript\nrequire('apostrophe')({\n  shortName: 'my-project',\n  modules: {\n    '@apostrophecms/login-totp': {}\n  }\n});\n```\n\nYou must configure the `@apostrophecms/login` module with a TOTP secret, as shown. The secret must be **exactly 10 characters long.**\n\n```javascript\n// modules/@apostrophecms/login/index.js\nmodule.exports = {\n  options: {\n    totp: {\n      // Should be a random string, exactly 10 characters long\n      secret: 'totpsecret'\n    }\n  }\n};\n```\n\n\u003e ⚠️ All configuration of TOTP related options is done on the `@apostrophecms/login` module. The `@apostrophecms/login-totp` module is just an \"improvement\" to that module, so it has no configuration options of its own.\n\n### Resetting TOTP when a user loses their device\n\nIf a user loses their device, an admin can edit the appropriate user via the admin bar. Select \"Yes\" for the \"Reset TOTP\" field and save the user.\n\nIf an admin user loses their own device, they can reset TOTP via a command line task. Pass the username as the sole argument:\n\n```\nnode app @apostrophecms/user:reset-totp username-goes-here\n```\n\nOnce TOTP is reset, the user is able to set it up again on their next login.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapostrophecms%2Flogin-totp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapostrophecms%2Flogin-totp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapostrophecms%2Flogin-totp/lists"}