Đăng xuất

Mô tả tổng quan

Tính năng Đăng xuất cung cấp cơ chế an toàn để kết thúc session người dùng trong ứng dụng. Khi người dùng đăng xuất, hệ thống vô hiệu hóa authentication tokens, xóa dữ liệu session và loại bỏ authentication cookies khỏi trình duyệt. Quy trình xử lý cả session người dùng thông thường và session đại diện chuyên biệt, đảm bảo loại bỏ hoàn toàn tất cả dấu vết xác thực cho mục đích bảo mật.

API: User Logout API

Sơ đồ hoạt động

---
config:
  theme: base
  layout: dagre
  flowchart:
    curve: linear
    htmlLabels: true
  themeVariables:
    edgeLabelBackground: "transparent"
---
flowchart TB
    %% Main components
    Client[Ứng dụng Client]
    LogoutController[LogoutController]
    AuthService(AuthService)
    CookieService((CookieService))
    SessionDB[(sessions)]

    Client --- Step1[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>1</span>
            <p style='margin-top: 8px'>Khởi tạo đăng xuất</p>
        </div>
    ]
    Step1 --> LogoutController

    LogoutController --- Step2[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>2</span>
            <p style='margin-top: 8px'>Xử lý đăng xuất</p>
        </div>
    ]
    Step2 --> AuthService

    AuthService --- Step3[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>3</span>
            <p style='margin-top: 8px'>Vô hiệu hóa Session chính</p>
        </div>
    ]
    Step3 --> SessionDB

    AuthService --- Step4[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>4</span>
            <p style='margin-top: 8px'>Vô hiệu hóa Session đại diện</p>
        </div>
    ]
    Step4 --> SessionDB

    AuthService --- Step5[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>5</span>
            <p style='margin-top: 8px'>Xóa Auth Cookies</p>
        </div>
    ]
    Step5 --> CookieService

    CookieService --- Step6[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>6</span>
            <p style='margin-top: 8px'>Trả về Response</p>
        </div>
    ]
    Step6 --> LogoutController

    LogoutController --- Step7[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>7</span>
            <p style='margin-top: 8px'>Trả về Response</p>
        </div>
    ]
    Step7 --> Client

    %% Styling
    style Client fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
    style LogoutController fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
    style AuthService fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style CookieService fill:#fcd9d9,stroke:#cc3333,stroke-width:2px
    style SessionDB fill:#ffe6cc,stroke:#ff9900,stroke-width:2px
    style Step1 fill:transparent,stroke:transparent,stroke-width:1px
    style Step2 fill:transparent,stroke:transparent,stroke-width:1px
    style Step3 fill:transparent,stroke:transparent,stroke-width:1px
    style Step4 fill:transparent,stroke:transparent,stroke-width:1px
    style Step5 fill:transparent,stroke:transparent,stroke-width:1px
    style Step6 fill:transparent,stroke:transparent,stroke-width:1px
    style Step7 fill:transparent,stroke:transparent,stroke-width:1px

API: Logout API

Tài liệu trường hợp

Trường hợp 1: Đăng xuất thành công

Mô tả

Người dùng đăng xuất thành công khỏi ứng dụng và tất cả dữ liệu session được xóa.

Sơ đồ tuần tự

sequenceDiagram
    participant User
    participant API as LogoutController
    participant Auth as AuthService
    participant Cookie as CookieService
    participant Session as SessionDB

    Note over User,API: Bước 1: Khởi tạo đăng xuất
    User->>API: POST /api/auth/logout
    
    Note over API,Auth: Bước 2: Xử lý đăng xuất
    API->>Auth: logout()
    
    Note over Auth,Session: Bước 3: Vô hiệu hóa Session chính
    Auth->>Session: Xóa bản ghi session
    Session-->>Auth: Xác nhận xóa
    
    Note over Auth,Session: Bước 4: Vô hiệu hóa Session đại diện
    Auth->>Session: Xóa session đại diện
    Session-->>Auth: Xác nhận xóa
    
    Note over Auth,Cookie: Bước 5: Xóa Auth Cookies
    Auth->>Cookie: forget(auth_api_token)
    Auth->>Cookie: forget(is_logged_in)
    Auth->>Cookie: forget(representative)
    
    Note over API,User: Bước 6: Trả về Response
    API-->>User: 200 OK với cookies đã xóa

Các bước

Bước 1: Khởi tạo đăng xuất

  • Mô tả: Người dùng yêu cầu đăng xuất khỏi ứng dụng
  • Request: GET /api/v1/general/auth/logout
  • Headers:
    • Authorization cookies tự động được bao gồm
  • Validation:
    • Kiểm tra nếu người dùng đã được xác thực
    • Xác minh session tồn tại

Bước 2: Xử lý đăng xuất

  • Mô tả: Controller khởi tạo quy trình đăng xuất
  • Hành động:
    • Gọi phương thức logout của Auth facade
    • Xử lý cả session chính và đại diện
    • Chuẩn bị xóa cookies

Bước 3: Vô hiệu hóa Session chính

  • Mô tả: Xóa session xác thực chính của người dùng
  • Hành động:
    • Xóa bản ghi session khỏi database
    • Loại bỏ user khỏi danh sách người dùng đã xác thực
    • Vô hiệu hóa session token
    • Ghi log kết thúc session

Bước 4: Vô hiệu hóa Session đại diện

  • Mô tả: Xóa session đại diện nếu có
  • Hành động:
    • Kiểm tra session đại diện đang hoạt động
    • Xóa bản ghi session đại diện
    • Loại bỏ context đại diện
    • Ghi log kết thúc session đại diện

Bước 5: Xóa Auth Cookies

  • Mô tả: Loại bỏ tất cả authentication cookies khỏi client
  • Hành động:
    • Tạo các instance cookie "forget" cho:
      • Auth API token cookie
      • Logged-in state cookie
      • Representative cookie
    • Đặt thời gian hết hạn cookie về quá khứ
    • Đảm bảo cookies sử dụng cùng domain/path như gốc
    • Đặt secure và httpOnly flags

Bước 6: Trả về Response

  • Mô tả: Gửi response thành công với hướng dẫn xóa cookies
  • Response:
    • Thành công: 200 OK với thông báo thành công
    • Đính kèm hướng dẫn xóa cookies vào response
    • Xóa cookie headers được định dạng đúng cho trình duyệt

Bảng dữ liệu liên quan

erDiagram
    sessions {
        bigint id PK
        string session_id "Định danh session duy nhất"
        bigint user_id FK "Tham chiếu đến bảng users"
        string guard_name "Tên authentication guard"
        string ip_address "Địa chỉ IP của client"
        string user_agent "User agent của client"
        text payload "Dữ liệu session"
        timestamp last_activity "Thời gian hoạt động cuối cùng"
        timestamp created_at
        timestamp updated_at
    }
    users {
        bigint id PK
        string name "Tên đầy đủ của người dùng"
        string email "Địa chỉ email của người dùng (duy nhất)"
        string status "Trạng thái tài khoản: active, inactive, suspended"
        timestamp created_at
        timestamp updated_at
    }

    sessions }o--|| users : thuộc về

Xử lý lỗi

  • Ghi log

    • Lỗi đăng xuất được ghi vào application logs
    • Chi tiết exception được ghi lại để debug
    • (Tùy chọn) Gửi slack message cho các sự kiện bảo mật
  • Chi tiết lỗi:

    Mã trạng thái Thông báo lỗi Mô tả
    401 "セッションが無効です。" Khi session không hợp lệ
    401 "ログアウトに失敗しました。" Khi đăng xuất thất bại
    401 Generic error với exception message Khi xảy ra lỗi không mong muốn

Trường hợp 2: Session Flush (Fallback)

Mô tả

Nếu đăng xuất bình thường thất bại, session flush được thực hiện để đảm bảo dữ liệu session được xóa.

Sơ đồ tuần tự

sequenceDiagram
    participant User
    participant API as LogoutController
    participant Session as SessionDB

    User->>API: GET /api/v1/general/auth/logout
    API->>API: thử đăng xuất bình thường
    Note over API: Exception xảy ra
    API->>Session: flush()
    API-->>User: 401 Unauthorized

Các bước

Bước 1: Thử đăng xuất bình thường

  • Mô tả: Hệ thống thử thủ tục đăng xuất tiêu chuẩn
  • Hành động: Giống như trường hợp thành công

Bước 2: Xử lý Exception

  • Mô tả: Bắt và xử lý các exception trong quá trình đăng xuất
  • Hành động:
    • Bắt exception trong try/catch block
    • Ghi log chi tiết exception
    • (Tùy chọn) Gửi slack notification

Bước 3: Emergency Flush

  • Mô tả: Buộc xóa tất cả dữ liệu session
  • Hành động:
    • Gọi phương thức session flush
    • Xóa tất cả bản ghi session cho user
    • Xóa tất cả cookies liên quan
    • Ghi log emergency flush event

Bước 4: Response lỗi

  • Mô tả: Thông báo cho client về vấn đề đăng xuất
  • Response:
    • Lỗi: 401 Unauthorized với exception message
    • Bao gồm hướng dẫn xóa cookies

Ghi chú bổ sung

  • Giới hạn tốc độ: Các lần thử đăng xuất bị giới hạn 10 lần mỗi phút cho mỗi địa chỉ IP
  • Đăng xuất được thiết kế để hoạt động nhất quán trên các loại user khác nhau (admin, thông thường, đại diện)
  • Cookies là domain-specific theo cài đặt cấu hình
  • Hệ thống xử lý cả các tình huống đăng xuất mong đợi và không mong đợi
  • Session flushing được sử dụng như biện pháp cuối cùng để đảm bảo bảo mật khi đăng xuất bình thường thất bại
  • Sau khi đăng xuất, người dùng thường được chuyển hướng đến trang đăng nhập bởi client application
  • Xem xét triển khai theo dõi hoạt động session cho giám sát