{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"d1c55d66-f063-4d2b-875e-f20c6c33f234","name":"Authentication Architecture Using DRF","description":"## ✨ Key Features\n\n### 🔐 Authentication & Security\n\n- **Custom JWT Authentication** - Custom token handling with rotation and validation\n    \n- **Session-Aware JWT Validation** - Sessions tracked and validated per device/browser\n    \n- **2FA Email-Based** - Additional security layer with email-based OTP verification\n    \n- **OAuth2 Integration** - Seamless Google login and registration\n    \n- **Rate Limiting & Lockout** - Automatic protection against brute force attacks\n    \n- **Security Notifications** - Real-time alerts for sensitive operations\n    \n\n### 📧 Email & Account Management\n\n- **Dual Verification Methods** - OTP or activation link for email verification\n    \n- **Password Reset Flow** - Secure password recovery via OTP or reset link\n    \n- **Email Change Request** - Verified email change workflow\n    \n- **Profile Management** - Update user details and profile image\n    \n\n### 🖥️ Session & Device Management\n\n- **Multi-Device Login** - Track and manage sessions across multiple devices\n    \n- **Login History** - Complete audit trail with IP, browser, OS details\n    \n- **Selective Logout** - Logout from specific device, selected sessions, or all devices\n    \n- **Device Tracking** - Identify browsers, OS, IP addresses, and user agents\n    \n\n### 🛡️ Advanced Protection\n\n- **Token Blacklisting** - Invalidate tokens on logout or password change\n    \n- **Account Lockout** - Progressive lockout after failed attempts\n    \n- **Password Change Security** - Automatic logout from all devices on password change\n    \n- **Account Deletion** - Secure permanent account removal with data cleanup\n    \n\n## 🔐 Security Behavior\n\nAfter logout:\n\n- The refresh token is blacklisted.\n    \n- The user session is marked inactive.\n    \n- Session-aware validation prevents access with tokens tied to inactive sessions.\n    \n\nAfter password change:\n\n- Existing sessions are revoked.\n    \n- Other devices are logged out.\n    \n- The user must authenticate again with the new password.\n    \n\nAccount protection includes:\n\n- OTP expiration\n    \n- OTP attempt locking\n    \n- Login rate limiting\n    \n- Account lockout after repeated failures\n    \n- Device, browser, OS, IP address, and user-agent tracking\n    \n- Security logging for sensitive authentication events\n    \n\n## Complete Workflow\n\nUsers can register with name, email, and password. After registration, the API sends a verification email containing both an activation link and an OTP, allowing the account to be activated through either method.\n\nUsers log in with email and password. If 2FA is enabled, the login process returns a temporary token and requires OTP verification before access and refresh tokens are issued. Users can enable, disable, and check 2FA status from protected endpoints.\n\nThe system also supports Google OAuth login and registration. Authenticated users can update their profile, request an email change, change password, reset forgotten passwords, review active sessions, inspect login history, log out from selected devices, log out from all devices, or permanently delete their account.\n\nSensitive operations are logged and protected with rate limits, account lockout rules, token blacklisting, session deactivation, and security notifications.","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":false,"owner":"48875561","team":10504389,"collectionId":"d1c55d66-f063-4d2b-875e-f20c6c33f234","publishedId":"2sBXqQFxV3","public":true,"publicUrl":"https://documenter-api.postman.tech/view/48875561/2sBXqQFxV3","privateUrl":"https://go.postman.co/documentation/48875561-d1c55d66-f063-4d2b-875e-f20c6c33f234","customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"documentationLayout":"classic-double-column","customisation":{"metaTags":[{"name":"description","value":""},{"name":"title","value":""}],"appearance":{"default":"light","themes":[{"name":"dark","logo":null,"colors":{"top-bar":"212121","right-sidebar":"303030","highlight":"FF6C37"}},{"name":"light","logo":null,"colors":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"}}]}},"version":"8.10.1","publishDate":"2026-05-16T14:22:51.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{"title":"","description":""},"logos":{"logoLight":null,"logoDark":null}},"statusCode":200},"environments":[{"name":"ENV","id":"33f2c07b-d2d2-4d1f-b570-78cdc1bd28a8","owner":"48875561","values":[{"key":"Base","value":"http://127.0.0.1:8000","enabled":true,"type":"default"},{"key":"Token","value":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzc4ODM0MDA3LCJpYXQiOjE3Nzg3NDQwMDcsImp0aSI6ImZlOTI5ODU5OGNjYjQ4MDNhZjAwNmYxZDcxZWE2OGQxIiwidXNlcl9pZCI6IjE3In0.kmh-NP90rTYEMnWdXyA9QXXHoK3zfSsKwbnt_pXn2N8","enabled":true,"type":"default"}],"published":true}],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/a3219d83bf6df9993a810acaff079ad4bca73197121699ff5d81e89cbe4109e8","favicon":""},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"},{"label":"ENV","value":"48875561-33f2c07b-d2d2-4d1f-b570-78cdc1bd28a8"}],"canonicalUrl":"https://documenter.gw.postman.com/view/metadata/2sBXqQFxV3"}