{"id":15018056,"url":"https://github.com/authifier/authifier","last_synced_at":"2026-01-18T06:47:47.589Z","repository":{"id":38100370,"uuid":"402399148","full_name":"authifier/authifier","owner":"authifier","description":"Opinionated Rust authentication library. Used for @revoltchat and @lightspeed-tv.","archived":false,"fork":false,"pushed_at":"2025-03-22T17:14:08.000Z","size":1794,"stargazers_count":43,"open_issues_count":11,"forks_count":14,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T04:07:41.961Z","etag":null,"topics":["rocket","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/authifier.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2021-09-02T11:43:28.000Z","updated_at":"2025-03-22T17:14:12.000Z","dependencies_parsed_at":"2024-09-16T12:32:27.297Z","dependency_job_id":"289bc433-4da0-43aa-b2cb-3e0447a9ddda","html_url":"https://github.com/authifier/authifier","commit_stats":{"total_commits":188,"total_committers":4,"mean_commits":47.0,"dds":"0.15957446808510634","last_synced_commit":"c4ef35567295dde241f74d27625261e718dd2cac"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/authifier%2Fauthifier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/authifier%2Fauthifier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/authifier%2Fauthifier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/authifier%2Fauthifier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/authifier","download_url":"https://codeload.github.com/authifier/authifier/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247289426,"owners_count":20914464,"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","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":["rocket","rust"],"created_at":"2024-09-24T19:51:22.640Z","updated_at":"2026-01-18T06:47:47.577Z","avatar_url":"https://github.com/authifier.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/authifier/authifier/blob/master/assets/Logo_GithubAutoTheme.svg\" height=\"180px\" /\u003e\n\u003c/p\u003e\n\n## Goals\n\n- Prevent user enumeration.\n\n  All routes should be protected against user enumeration.\n\n- Always confirm any change to security settings using two-factor method if available.\n- Prevent phishing attacks.\n\n## Play around with Authifier API\n\nYou can play around with the API by using the provided example and using Swagger:\n\n```bash\n# Clone the project\ngit clone https://github.com/insertish/authifier\ncd authifier\n\n# Bring up MongoDB\ndocker-compose up -d database\n\n# Start the example\ncargo run --example rocket_mongodb --features example\n```\n\nNow you can navigate to http://localhost:8000/swagger!\n\n## Usage\n\nGetting started is very simple, first add Authifier to your `Cargo.toml`:\n\n```toml\n[dependencies]\nauthifier = { version = \"1.0\", features = [ \"rocket_impl\", \"okapi_impl\", \"async-std-runtime\", \"database-mongodb\" ] }\nrocket_authifier = { version = \"1.0\" }\n\n# For the example below, you also need:\nrocket = { version = \"0.5.0-rc.2\", default-features = false, features = [\"json\"] }\nmongodb = { version = \"2.2.1\", default-features = false, features = [\"async-std-runtime\"] }\n```\n\nThen you can create a new instance of Authifier and mount it on to Rocket.\n\n```rust\n#[macro_use]\nextern crate rocket;\n\nuse mongodb::{options::ClientOptions, Client};\nuse authifier::database::MongoDb;\nuse authifier::Migration;\n\n#[launch]\nasync fn rocket() -\u003e _ {\n  // Prepare MongoDB configuration\n  let client_options = ClientOptions::parse(\"mongodb://localhost:27017\")\n    .await\n    .expect(\"Valid connection URL\");\n\n  // Connect to MongoDB\n  let client = Client::with_options(client_options).expect(\"MongoDB server\");\n\n  // Prepare Authifier database abstraction\n  let database = authifier::Database::MongoDb(MongoDb(client.database(\"authifier\")));\n\n  // Run database migrations\n  // TODO: you should only run this once and have this as part of your migrations\n  // Also keep this up to date with the \"migrations\" section down below this one.\n  database.run_migration(Migration::M2022_06_03EnsureUpToSpec).await.unwrap();\n\n  // Configure Authifier however you need to\n  let authifier = authifier::Authifier {\n    database,\n    ..Default::default()\n  };\n\n  // Build your web server as usual...\n  rocket::build()\n    // Attach the configuration as state\n    .manage(authifier)\n    // Mount authentication routes\n    .mount(\"/auth/account\", rocket_authifier::routes::account::routes().0)\n    .mount(\"/auth/session\", rocket_authifier::routes::session::routes().0)\n    .mount(\"/auth/mfa\", rocket_authifier::routes::mfa::routes().0)\n}\n```\n\n## Testing\n\nTo test the library, pull up required services:\n\n```bash\n# Start MongoDB and Sendria\ndocker-compose up -d\n```\n\nThen you can run the tests:\n\n```bash\n# Run cargo test\ncargo test --features test\n\n# Or using nextest\ncargo nextest run --features test\n```\n\nRun a coverage test:\n\n```bash\n# Run tarpaulin\ncargo tarpaulin --features test --out html\n```\n\n## Database Migrations\n\nMigrating the database is easy, you should orchestrate it yourself, ideally you have your own versioned migration system which you can slot changes into.\n\nBut, by default, migrations will not run if the system detects that it has probably already been applied.\n\n```rust\nuse authifier::{ Database, Migration };\n\n// Acquire the database first\nlet database = Database::[..];\n\n// Then run a specific migration\ndatabase.run_migration(Migration::[..]).await.unwrap();\n```\n\nThe following migrations are available and must be run in order:\n\n| Date       | Migration                         | Description                                                                                          |\n| ---------- | --------------------------------- | ---------------------------------------------------------------------------------------------------- |\n| 2022-06-03 | `M2022_06_03EnsureUpToSpec`       | Reset and reconstruct indexes to be fully up to date. This will also create any missing collections. |\n| 2022-06-09 | `M2022_06_09AddIndexForDeletion`  | Add an index for account deletion information.                                                       |\n| 2025-02-20 | `M2025_02_20AddLastSeenToSession` | Add last_seen to sessions table.                                                                     |\n\n## How does Authifier work?\n\nAuthifier uses email / password combinations to authenticate users and nothing else, this might not be what you're looking for but I personally prefer this format.\n\n- If you need usernames, you need to handle this on your end.\n\nWhen a user signs in, a new session is created, every single device a user logs in on has a unique session.\n\n- This means a user can then log themselves out of old sessions or otherwise see where they are logged in.\n\n![Example from Revolt App](https://img.insrt.uk/xexu7/daLinuSa38.png/raw)\n\nInternally Authifier stores emails with and without special characters, `+.`.\n\n- This means we can support plus signing without allowing the same email to sign up multiple times.\n  - For example, `inbox+a@example.com` and `inbox+b@example.com` are treated as equal.\n  - But since we are still storing the original email, we still send them marked with the user's sign.\n- In the case of Gmail, all emails with dots are forwarded to those without them, this can lead to some [unfortunate situations](https://jameshfisher.com/2018/04/07/the-dots-do-matter-how-to-scam-a-gmail-user/).\n  - Generally, we treat all emails with dots as their non-dot counterpart when checking if an email exists.\n  - This may inconvenience some users but I would rather avoid situations like above or duplicate accounts.\n- When logging in, we use the normalised email to find the correct account.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fauthifier%2Fauthifier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fauthifier%2Fauthifier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fauthifier%2Fauthifier/lists"}