{"id":31949781,"url":"https://github.com/rickyc0626/authentication-example","last_synced_at":"2026-04-11T17:05:28.729Z","repository":{"id":63607425,"uuid":"567537599","full_name":"RickyC0626/authentication-example","owner":"RickyC0626","description":"⚗️ An example authentication system with registration and login forms","archived":false,"fork":false,"pushed_at":"2024-04-11T05:17:51.000Z","size":966,"stargazers_count":1,"open_issues_count":12,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-06-28T16:39:28.089Z","etag":null,"topics":["authentication","axios","bcrypt","expressjs","jwt","mongodb","nextjs","nodejs","react","styled-components","tailwindcss","typescript"],"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/RickyC0626.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}},"created_at":"2022-11-18T02:03:34.000Z","updated_at":"2024-06-28T14:12:02.000Z","dependencies_parsed_at":"2023-02-08T15:15:48.390Z","dependency_job_id":null,"html_url":"https://github.com/RickyC0626/authentication-example","commit_stats":null,"previous_names":["rickyc0626/authentication-example"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/RickyC0626/authentication-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickyC0626%2Fauthentication-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickyC0626%2Fauthentication-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickyC0626%2Fauthentication-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickyC0626%2Fauthentication-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RickyC0626","download_url":"https://codeload.github.com/RickyC0626/authentication-example/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickyC0626%2Fauthentication-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279018639,"owners_count":26086577,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["authentication","axios","bcrypt","expressjs","jwt","mongodb","nextjs","nodejs","react","styled-components","tailwindcss","typescript"],"created_at":"2025-10-14T12:35:42.837Z","updated_at":"2025-10-14T12:35:43.748Z","avatar_url":"https://github.com/RickyC0626.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# authentication-example\nAn example authentication system with registration and login forms\n\n## Showcase\n\n### Login Page\n![Login Page](/assets/login-page.png)\n\n### Signup Page\n![Signup Page](/assets/signup-page.png)\n\n### Dashboard (Logged In)\n![Dashboard after logging in](/assets/dashboard.png)\n\n## Roadmap\n\n### UI\n\n#### Login Form\n- [X] Page URL `/`\n- [X] Field for username\n- [X] Field for password\n- [X] \"Login\" button\n- [X] \"Sign Up\" button\n  - [X] When clicked, show registration form at `/signup`\n\n#### Registration Form\n- [X] Page URL `/signup`\n- [X] Field for username\n  - [X] Regex pattern: alphanumeric w/ underscore, 3-30 characters\n  - [X] Show error in form when pattern does not match\n- [X] Field for email\n  - [X] Regex pattern: https://www.emailregex.com/\n- [X] Field for password\n  - [X] Regex pattern: at least 1 uppercase, 1 lowercase, 1 decimal digit, 8+ characters\n  - [X] Show error in form when pattern does not match\n- [X] Field for confirm password\n  - [X] Valid only if it matches password\n  - [X] Show error in form when pattern does not match\n- [X] \"Create account\" button\n- [X] On successful signup, redirect to login page at `/`\n\n#### Home Page (Dashboard)\n- [X] Base URL `/`\n- [X] Redirect to here when login successful\n- [ ] Main content is placeholder kanban columns (just backgrounds)\n- [X] Logout button\n\n### Server\n\n#### REST API\n- [ ] `POST /signup` - Create new account\n  - [X] Request body contains `username`, `email` and `password`\n  - [X] Hashes password with salt\n  - [X] Persists new user account in database\n    - [X] Field for verified email status\n    - [ ] If email unverified, delete account after 15 minutes\n    - [ ] If email verified, set verified email status to true, don't delete\n  - [ ] Sends email verification with one-time code, set to expire in 10 minutes\n  - [X] Respond with status code `201 Created` on success\n  - [X] Respond with status code `500 Internal Server Error` on failure\n- [ ] `POST /login` - Login with credentials\n  - [X] Request body contains `username` and `password`\n  - [X] Retrieves user from database by `username`\n  - [X] Compares password hashes with stored hash\n  - [ ] Sends email verification with one-time code, set to expire in 10 minutes\n  - [X] Sends limited use access token (1 hr) to use in browser as response\n    - [X] Has max age (time of expiration)\n    - [X] If expired, a new token will have to be generated using refresh token\n  - [X] Respond with status code `200 OK` on success\n  - [X] Respond with status code `403 Forbidden` on failure\n  - [X] Respond with status code `500 Internal Server Error` on general failure\n- [X] `GET /refresh` - Generate new access token using refresh token\n  - [X] Header contains authorization bearer refresh token\n  - [X] If there's no token, return `406 Not Acceptable`\n  - [X] If token is wrong or expired, return `406 Not Acceptable`\n  - [X] If token is verified, return `200 OK` with new access token as payload\n- [X] `GET /` - Gain authorized access to homepage (verification middleware)\n  - [X] Header contains authorization bearer access token\n  - [X] If there's no token, return `401 Unauthorized`\n  - [X] If token is wrong or expired, return `403 Forbidden`\n  - [X] If token is verified, return `200 OK`\n- [ ] `GET /verify` - Verify new account\n  - [ ] Request body contains `accountId` and `otp`\n  - [ ] Checks if `otp` has expired (compare current time to expiry timestamp)\n  - [ ] Verifies one-time code, allows sending access token to user after next login\n  - [ ] Allows only 3 failed attempts before voiding the code\n    - [ ] Redirects to login page after voiding\n\n#### Persistence (Database)\n- [X] Setup MongoDB","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frickyc0626%2Fauthentication-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frickyc0626%2Fauthentication-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frickyc0626%2Fauthentication-example/lists"}