سی ام اس نویسسی ام اس نویسیاد بگیر، سیستم خودتو بنویس
مجلهتماس با ما
سی ام اس نویسسی ام اس نویس

CMS نویس مرجعی برای آموزش برنامه نویسی وب و PHP، توسعه افزونه‌های اختصاصی وردپرس، طراحی ورک‌فلو و اتوماسیون با n8n و توسعه CMS های اختصاصی است. هدف ما ارائه آموزش‌های کاربردی و راهکارهای حرفه‌ای برای توسعه‌دهندگان، کسب‌وکارها و علاقه‌مندان به دنیای برنامه‌نویسی است.

پیوندهای سریع
محصولات فیزیکیمحصولات دیجیتالدوره‌های آموزشی
سی ام اس نویس
مجله سی ام اس نویستماس با ماپنل کاربری
سی ام اس نویس — تمامی حقوق برای سی ام اس نویس محفوظ است. © 1406 تماس با ما09307711941
پیاده‌سازی Front-Channel Logout در OpenID Connect با PHP؛ مدیریت خروج کاربر از چند اپلیکیشن

پیاده‌سازی Front-Channel Logout در OpenID Connect با PHP؛ مدیریت خروج کاربر از چند اپلیکیشن

ممدیر کل سیستم ۴ مهر ۱۴۰۵ ۱۹ دقیقه مطالعه ۰ بازدید
پیاده‌سازی Front-Channel Logout در OpenID Connect با PHP؛ مدیریت خروج کاربر از چند اپلیکیشن

مقدمه

در یک سیستم ساده، Logout معمولاً کار پیچیده‌ای نیست.

کاربر روی دکمه «خروج» کلیک می‌کند، Session حذف می‌شود و کاربر به صفحه Login منتقل می‌شود.

اما در یک معماری SSO، شرایط متفاوت است.

فرض کنید یک مجموعه چند اپلیکیشن دارد:


auth.example.com

shop.example.com

panel.example.com

portal.example.com

و همه این اپلیکیشن‌ها از یک Identity Provider مرکزی استفاده می‌کنند.

کاربر ممکن است با یک Login در چند اپلیکیشن Session داشته باشد.

حالا اگر از Identity Provider خارج شود، باید بتوانیم به اپلیکیشن‌های مختلف اطلاع دهیم که Session مربوط به کاربر باید بسته شود.

در مقاله قبل با Back-Channel Logout آشنا شدیم؛ روشی که در آن Identity Provider مستقیماً از Backend اپلیکیشن‌ها درخواست Logout می‌کند.

اما روش دیگری نیز وجود دارد که ارتباط را از طریق مرورگر کاربر انجام می‌دهد:

Front-Channel Logout

در این مقاله ابتدا Front-Channel Logout را به‌صورت کامل بررسی می‌کنیم، سپس معماری آن را می‌سازیم، نحوه استفاده از iframe را توضیح می‌دهیم، Sessionهای PHP را مدیریت می‌کنیم و در نهایت تفاوت آن را با Back-Channel Logout و OIDC Session Management بررسی خواهیم کرد.


# Front-Channel Logout چیست؟

Front-Channel Logout یکی از روش‌های Logout در معماری OpenID Connect است که در آن Identity Provider از User Agent یا Browser کاربر برای اطلاع‌رسانی Logout به Relying Partyها استفاده می‌کند.

به‌صورت ساده:


User

 │

 │ Logout

 ▼

Identity Provider

 │

 │ Browser

 ▼

RP Logout Pages

 │

 ├── Shop

 ├── Panel

 └── Portal

بنابراین برخلاف Back-Channel Logout، ارتباط Logout مستقیماً از Backend OP به Backend RP انجام نمی‌شود.

Browser نقش واسطه را دارد.


# Front-Channel در مقابل Back-Channel

تفاوت اصلی این دو روش در مسیر ارتباط است.

Back-Channel


OP

 │

 │ Server-to-Server

 ▼

RP

Front-Channel


OP

 │

 │ Browser

 ▼

RP

در Front-Channel معمولاً OP صفحه‌ای را نمایش می‌دهد که Logout Endpointهای RPها را در خود قرار داده است.

این کار معمولاً با iframe انجام می‌شود.


# معماری Front-Channel Logout

فرض کنیم سه اپلیکیشن داریم:


shop.example.com

panel.example.com

portal.example.com

و Identity Provider:


auth.example.com

پس از Logout:


                 Identity Provider

                         │

                         ▼

                    Logout Page

                         │

              ┌──────────┼──────────┐

              │          │          │

              ▼          ▼          ▼

           iframe      iframe      iframe

              │          │          │

              ▼          ▼          ▼

            Shop       Panel       Portal

هر iframe یک Logout URL مربوط به یک RP را باز می‌کند.


# Front-Channel Logout چه مشکلی را حل می‌کند؟

فرض کنیم کاربر در این اپلیکیشن‌ها Session دارد:


Shop

Panel

Portal

اگر فقط Session مربوط به Identity Provider بسته شود، Sessionهای محلی این اپلیکیشن‌ها لزوماً به‌صورت خودکار حذف نمی‌شوند.

Front-Channel Logout به OP اجازه می‌دهد از طریق Browser به RPها اطلاع دهد:


کاربر Logout کرده است.

Session محلی را ببند.


# Front-Channel Logout URI چیست؟

هر RP می‌تواند یک Logout URI ثبت کند.

برای مثال:


https://shop.example.com/oidc/frontchannel-logout

یا:


https://panel.example.com/oidc/frontchannel-logout

Identity Provider هنگام Logout از این URLها استفاده می‌کند.


# ثبت Front-Channel Logout URI

اطلاعات Client می‌تواند چیزی شبیه این باشد:


{

    "client_id": "shop-client",

    "frontchannel_logout_uri":

        "https://shop.example.com/oidc/frontchannel-logout"

}

برای اپلیکیشن دیگر:


{

    "client_id": "panel-client",

    "frontchannel_logout_uri":

        "https://panel.example.com/oidc/frontchannel-logout"

}

Identity Provider باید این URLها را در زمان Registration معتبر و مشخص نگه دارد.


# چرا Logout URL باید از قبل ثبت شود؟

یکی از خطرهای مهم در سیستم‌های Authentication، Open Redirect است.

اگر OP اجازه دهد هر URL دلخواهی در زمان Logout ارسال شود، مهاجم می‌تواند کاربر را به یک سایت دیگر هدایت کند.

بنابراین باید فقط URLهایی استفاده شوند که قبلاً برای Client ثبت شده‌اند.

مثلاً:


client_id = shop-client



registered:

https://shop.example.com/oidc/frontchannel-logout

و نه:


https://attacker.example/logout


# نقش iframe در Front-Channel Logout

یکی از روش‌های اصلی پیاده‌سازی Front-Channel Logout استفاده از iframe است.

مثلاً صفحه Logout در OP می‌تواند شامل چیزی شبیه این باشد:


<iframe

    src="https://shop.example.com/oidc/frontchannel-logout">

</iframe>



<iframe

    src="https://panel.example.com/oidc/frontchannel-logout">

</iframe>



<iframe

    src="https://portal.example.com/oidc/frontchannel-logout">

</iframe>

Browser این URLها را بارگذاری می‌کند.

هر RP نیز با دریافت Request، Session محلی مربوط به کاربر را مدیریت می‌کند.


# چرا iframe استفاده می‌شود؟

مزیت iframe این است که OP می‌تواند چند Logout Endpoint را هم‌زمان در یک صفحه بارگذاری کند.

مثلاً:


Logout Page

│

├── iframe → Shop

├── iframe → Panel

└── iframe → Portal

بدون اینکه کاربر مجبور باشد تک‌تک این صفحات را مشاهده کند.


# مشکل مهم iframe

در اینجا یک مسئله بسیار مهم وجود دارد:

Third-Party Cookie

مرورگرهای مدرن محدودیت‌های بیشتری روی Cookieهایی که در Contextهای Third-Party استفاده می‌شوند اعمال کرده‌اند.

فرض کنید کاربر روی:


auth.example.com

قرار دارد و داخل iframe صفحه زیر باز می‌شود:


shop.example.com

Cookie مربوط به shop.example.com ممکن است در این Context تحت محدودیت‌های Browser قرار بگیرد.

در نتیجه RP ممکن است نتواند Session Cookie معمول خود را به همان شکلی که انتظار داریم دریافت کند.

این یکی از مهم‌ترین محدودیت‌های معماری Front-Channel Logout است.


# چرا Cookie برای Front-Channel اهمیت دارد؟

فرض کنید Session PHP ما با Cookie زیر مدیریت می‌شود:


PHPSESSID

در حالت عادی:


Browser

 ↓

shop.example.com

 ↓

PHP Session

اما در iframe:


auth.example.com

 ↓

iframe

 ↓

shop.example.com

Browser ممکن است Cookieهای مربوط به shop.example.com را با محدودیت‌های خاصی ارسال کند.

بنابراین طراحی Cookie و سیاست‌های SameSite اهمیت زیادی پیدا می‌کند.


# SameSite چیست؟

Cookie می‌تواند یک ویژگی مانند زیر داشته باشد:


Set-Cookie:

PHPSESSID=abc123;

Secure;

HttpOnly;

SameSite=Lax

مقدار SameSite تعیین می‌کند Cookie در چه Contextهایی ارسال شود.

مقادیر متداول:


Strict

Lax

None

برای سناریوهای Cross-Site، رفتار SameSite=None با Secure می‌تواند مطرح شود، اما انتخاب آن باید بر اساس معماری واقعی و مدل تهدید انجام شود.


# آیا Front-Channel Logout همیشه کار می‌کند؟

خیر.

این نکته بسیار مهم است.

Front-Channel Logout به Browser وابسته است و رفتار Browser، Cookie Policy، iframe Policy و سیاست‌های Privacy می‌توانند روی آن اثر بگذارند.

بنابراین نباید Front-Channel Logout را به‌عنوان یک ارتباط کاملاً قابل‌اعتماد Server-to-Server در نظر گرفت.

اگر نیاز به Logout سمت Backend با وابستگی کمتر به Browser دارید، Back-Channel Logout معماری متفاوتی ارائه می‌دهد.


# Front-Channel Logout و Session کاربر

فرض کنیم Session محلی Shop به شکل زیر است:


user_id = 25

session_id = abc123

وقتی Browser Logout Endpoint را باز می‌کند، RP باید Session مربوط به کاربر را ببندد.

اما یک سؤال مهم وجود دارد:

RP از کجا بفهمد این Request مربوط به کدام Session است؟

در اینجا Session Cookie و طراحی Session Management اهمیت زیادی پیدا می‌کند.


# Session Management در PHP

یک پیاده‌سازی ساده PHP ممکن است از:


session_start();

استفاده کند.

و Session کاربر را از:


$_SESSION

بخواند.

اما در Front-Channel Logout نباید فقط به این موضوع تکیه کنیم.

چون هدف اصلی این است که Logout با Session مربوط به همان OP Session هماهنگ شود.

به همین دلیل بهتر است هنگام Login، ارتباط بین:


OP Session

Local Session

User

Client

را ذخیره کنیم.


# طراحی جدول Session

مثلاً:


CREATE TABLE oidc_sessions (

    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,

    user_id BIGINT UNSIGNED NOT NULL,

    client_id VARCHAR(255) NOT NULL,

    op_sid VARCHAR(255) NULL,

    local_session_id_hash CHAR(64) NOT NULL,

    created_at TIMESTAMP NULL,

    last_seen_at TIMESTAMP NULL,

    revoked_at TIMESTAMP NULL

);

این جدول در معماری چند اپلیکیشنی بسیار مفید است.


# ارتباط Sessionها

فرض کنید:


User

 │

 ├── OP Session: SID-100

 │

 ├── Shop Session: PHP-ABC

 │

 ├── Panel Session: PHP-DEF

 │

 └── Portal Session: PHP-GHI

Front-Channel Logout باید بتواند Session محلی مناسب را پیدا کند و ببندد.


# Logout Endpoint در PHP

یک Endpoint ساده:


<?php



if ($_SERVER['REQUEST_METHOD'] !== 'GET') {

    http_response_code(405);

    exit;

}



session_start();



$_SESSION = [];



if (ini_get('session.use_cookies')) {



    $params = session_get_cookie_params();



    setcookie(

        session_name(),

        '',

        time() - 42000,

        $params['path'],

        $params['domain'],

        $params['secure'],

        $params['httponly']

    );

}



session_destroy();



http_response_code(200);

این نمونه فقط نشان‌دهنده مکانیزم عمومی بستن Session PHP است.

در یک سیستم OIDC واقعی، باید ارتباط Session با OP Session نیز به‌درستی مدیریت شود.


# چرا Logout Endpoint نباید فقط Session فعلی را حذف کند؟

فرض کنید:


User 25

چند Session دارد:


Session A

Session B

Session C

اگر Request مربوط به Logout فقط بتواند Session فعلی Browser را ببندد، ممکن است Sessionهای دیگر همچنان فعال باقی بمانند.

به همین دلیل طراحی Session Mapping اهمیت دارد.


# Session ID در Front-Channel Logout

در برخی معماری‌ها از اطلاعاتی مانند sid برای مشخص کردن Session استفاده می‌شود.

اگر معماری RP و OP امکان ارتباط Session را فراهم کرده باشد، می‌توان Session محلی را بر اساس شناسه Session مربوط به OP پیدا کرد.

مثلاً:


sid = OP-SESSION-123

و Database:


op_sid = OP-SESSION-123

سپس:


UPDATE oidc_sessions

SET revoked_at = NOW()

WHERE op_sid = ?

AND client_id = ?;


# مشکل مهم: اطلاعات شناسایی Session

Front-Channel Logout با Back-Channel Logout یکسان نیست.

در Back-Channel، OP می‌تواند Logout Token را به RP ارسال کند.

در آن Token اطلاعاتی مانند:


iss

aud

sid

sub

events

jti

وجود دارد.

اما در Front-Channel باید مکانیزم تعریف‌شده برای انتقال اطلاعات Logout را مطابق پروتکل و Registration مورد استفاده قرار داد.

بنابراین نباید فرض کنیم که هر Front-Channel Request دقیقاً همان اطلاعات Logout Token را دارد.


# Front-Channel Logout URI با Query Parameter

در معماری‌هایی که Logout URI باید اطلاعات Session را دریافت کند، ممکن است URL با Query Parameter ساخته شود.

مثلاً:


https://shop.example.com/oidc/frontchannel-logout?sid=abc123

اما باید دقت کرد که:

هر Query Parameter قابل اعتمادی نیست.

اگر sid از URL دریافت می‌شود، نباید صرفاً به وجود آن اعتماد کنیم.

باید بررسی کنیم که Session مربوط به همان Client و همان OP باشد و امکان سوءاستفاده وجود نداشته باشد.


# اعتبارسنجی اطلاعات Logout

یک اصل مهم:


User input ≠ Trusted input

حتی اگر Request از صفحه Identity Provider آمده باشد، نباید همه اطلاعات URL را بدون بررسی قبول کنیم.

در طراحی امن باید اطلاعات مربوط به Session با داده‌های ثبت‌شده در سیستم مقایسه شوند.


# جریان کامل Front-Channel Logout

یک Flow معمول را می‌توان این‌گونه تصور کرد:


User

 │

 │ Click Logout

 ▼

Identity Provider

 │

 │ Close OP Session

 │

 ▼

Logout Page

 │

 ├── iframe → Shop

 │

 ├── iframe → Panel

 │

 └── iframe → Portal

       │

       ▼

  Local Session Logout

پس از آن کاربر می‌تواند به صفحه نهایی Logout منتقل شود.


# پیاده‌سازی Logout Page در PHP

فرض کنیم OP اطلاعات RPها را از Database گرفته باشد:


$rps = [

    'https://shop.example.com/oidc/frontchannel-logout',

    'https://panel.example.com/oidc/frontchannel-logout',

    'https://portal.example.com/oidc/frontchannel-logout',

];

سپس:


foreach ($rps as $logoutUrl) {

    echo '<iframe src="' .

        htmlspecialchars($logoutUrl, ENT_QUOTES, 'UTF-8') .

        '" hidden></iframe>';

}

این فقط یک نمونه ساده آموزشی است.

در Production باید URLها فقط از Client Registration معتبر سیستم استخراج شوند.


# چرا نباید URL را از Request کاربر بگیریم؟

این کار خطرناک است:


$url = $_GET['logout_url'];



echo '<iframe src="' . $url . '"></iframe>';

چون مهاجم می‌تواند مقدار دلخواه ارسال کند:


?logout_url=https://attacker.example

این موضوع می‌تواند زمینه Open Redirect یا سوءاستفاده‌های دیگر را ایجاد کند.

URL باید از Client Registration یا Configuration معتبر سیستم استخراج شود.


# جلوگیری از Clickjacking

Endpointهای حساس باید سیاست‌های مناسب Browser را داشته باشند.

اما یک نکته مهم وجود دارد:

اگر صفحه‌ای قرار است عمداً در iframe توسط OP بارگذاری شود، نباید به‌صورت ساده سیاستی تنظیم کنیم که تمام iframeها را مسدود کند.

برای مثال:


X-Frame-Options: DENY

ممکن است با معماری Front-Channel Logout ناسازگار باشد.

در عوض باید سیاست CSP و frame-ancestors با معماری واقعی هماهنگ شود.


# Content Security Policy

برای صفحات حساس می‌توان از CSP استفاده کرد.

مثلاً:


Content-Security-Policy:

frame-ancestors https://auth.example.com

هدف این است که مشخص کنیم چه Originهایی اجازه دارند صفحه موردنظر را داخل Frame قرار دهند.

مقدار واقعی باید مطابق Originهای مورد اعتماد سیستم باشد.


# چرا frame-ancestors مهم است؟

فرض کنید Logout Endpoint شما:


https://shop.example.com/oidc/frontchannel-logout

باشد.

نمی‌خواهیم هر سایت ناشناسی بتواند آن را داخل iframe قرار دهد.

به همین دلیل می‌توان Parent Origin مورد اعتماد را محدود کرد.


# تفاوت Front-Channel Logout و Back-Channel Logout

ویژگیFront-ChannelBack-Channel
مسیر ارتباطBrowserServer-to-Server
وابستگی به Browserزیادکم
استفاده از iframeمعمولاً بلهخیر
وابستگی به Cookieممکن استبسیار کمتر
ارتباط مستقیم OP → RP Backendخیربله
تأثیر Browser Privacyبیشترکمتر
اجرای Logout در Backendغیرمستقیممستقیم
مناسب برایBrowser-based flowsBackend-centric architecture

هیچ‌کدام را نباید صرفاً بر اساس نام، جایگزین کامل دیگری فرض کرد؛ انتخاب معماری به نیاز سیستم بستگی دارد.


# Front-Channel Logout و OIDC Session Management

این سه مفهوم نیز نباید با یکدیگر ترکیب شوند:


OIDC Session Management

Front-Channel Logout

Back-Channel Logout

OIDC Session Management

هدف اصلی آن تشخیص تغییر وضعیت Session در OP است.

Front-Channel Logout

OP از طریق Browser به RPها Logout را منتقل می‌کند.

Back-Channel Logout

OP مستقیماً به Backend RP اطلاع می‌دهد.


# Front-Channel Logout و RP-Initiated Logout

در RP-Initiated Logout:


RP

 ↓

OP

شروع Logout از RP انجام می‌شود.

اما در Front-Channel Logout:


OP

 ↓

Browser

 ↓

RP

OP فرآیند اطلاع‌رسانی Logout به RP را انجام می‌دهد.

این دو مفهوم می‌توانند در یک معماری کنار یکدیگر استفاده شوند.


# آیا Front-Channel Logout Session را واقعاً حذف می‌کند؟

بستگی به پیاده‌سازی RP دارد.

دریافت Request به‌تنهایی کافی نیست.

RP باید:

  1. Session را شناسایی کند.
  2. Session را Revoked یا Destroy کند.
  3. اطلاعات مربوط به Session را به‌روزرسانی کند.
  4. در صورت نیاز Tokenهای مربوطه را مدیریت کند.

مثلاً:


$session->revoke();

و سپس:


session_destroy();


# Access Token و Refresh Token چه می‌شوند؟

Logout Session محلی لزوماً به معنی Revocation خودکار تمام Tokenها نیست.

اگر سیستم شما از Access Token و Refresh Token استفاده می‌کند، باید سیاست Token Lifecycle نیز جداگانه طراحی شود.

مثلاً هنگام Logout می‌توان:


Local Session

      ↓

Revoke

      ↓

Refresh Token

      ↓

Revoke

را در نظر گرفت.

برای JWTهای Stateless نیز باید توجه داشت که Logout محلی به‌تنهایی الزاماً JWT صادرشده قبلی را بی‌اعتبار نمی‌کند.


# استفاده از Queue در Front-Channel Logout

Front-Channel ذاتاً Browser-based است، بنابراین نباید آن را با Queue اشتباه گرفت.

Queue بیشتر در عملیات Backend مانند:


Token Revocation

Audit Logging

Cleanup

Notifications

می‌تواند استفاده شود.

اما خود Front-Channel Notification توسط Browser و iframe انجام می‌شود.


# مشکلات عملی Front-Channel Logout

چند مشکل رایج:

۱. Cookie ارسال نمی‌شود

به‌دلیل سیاست Browser یا SameSite.

۲. iframe مسدود می‌شود

به‌دلیل CSP یا X-Frame-Options.

۳. Browser Privacy

برخی Browserها Third-Party Contextها را محدود می‌کنند.

۴. RP در دسترس نیست

iframe نمی‌تواند Endpoint را باز کند.

۵. Session قابل شناسایی نیست

RP نمی‌داند کدام Session باید بسته شود.

۶. Logout فقط ظاهری است

صفحه Logout نمایش داده می‌شود اما Session واقعی همچنان فعال است.


# آیا می‌توان Front-Channel و Back-Channel را با هم داشت؟

بله.

در یک معماری پیچیده ممکن است از چند مکانیزم برای نیازهای مختلف استفاده شود.

مثلاً:


User Logout

     │

     ▼

Identity Provider

     │

     ├── Front-Channel → Browser-based RP Logout

     │

     └── Back-Channel → Backend Session Logout

اما نباید بدون نیاز، پیچیدگی غیرضروری به سیستم اضافه کرد.

هر مکانیزم باید دلیل مشخصی در معماری داشته باشد.


# نمونه معماری کامل SSO

یک معماری چنداپلیکیشنی را در نظر بگیریم:


                    ┌─────────────────────┐

                    │ Identity Provider   │

                    │ auth.example.com    │

                    └──────────┬──────────┘

                               │

                         Logout Request

                               │

                               ▼

                        ┌─────────────┐

                        │ Logout Page │

                        └──────┬──────┘

                               │

                 ┌─────────────┼─────────────┐

                 │             │             │

                 ▼             ▼             ▼

               Shop          Panel         Portal

                 │             │             │

                 ▼             ▼             ▼

             Session        Session       Session

              Revoke         Revoke        Revoke

در چنین معماری‌ای OP مسئول هماهنگ‌سازی فرآیند است و هر RP مسئول مدیریت Session محلی خودش است.


# ساختار پیشنهادی پروژه PHP

برای یک پروژه PHP تمیز می‌توان ساختار زیر را داشت:


app/

├── Controllers/

│   └── OidcFrontChannelLogoutController.php

│

├── Services/

│   ├── OidcSessionManager.php

│   └── FrontChannelLogoutService.php

│

├── Repositories/

│   └── OidcSessionRepository.php

│

└── Models/

    └── OidcSession.php

Controller:


class OidcFrontChannelLogoutController

{

    public function handle()

    {

        return app(

            FrontChannelLogoutService::class

        )->handle();

    }

}

Service:


class FrontChannelLogoutService

{

    public function handle(): void

    {

        $session = $this

            ->sessionRepository

            ->findCurrentSession();



        if (!$session) {

            return;

        }



        $this->sessionManager

            ->revoke($session);

    }

}

این ساختار باعث می‌شود منطق Business از Controller جدا باشد.


# Front-Channel Logout در Laravel

اگر پروژه با Laravel ساخته شده باشد، می‌توان Route زیر را ایجاد کرد:


Route::get(

    '/oidc/frontchannel-logout',

    [

        OidcFrontChannelLogoutController::class,

        'handle'

    ]

);

سپس Controller:


class OidcFrontChannelLogoutController

{

    public function handle(

        Request $request

    ) {

        app(

            OidcSessionManager::class

        )->logoutCurrentSession();



        return response('', 204);

    }

}

اما در یک پیاده‌سازی واقعی، Session Identification باید مطابق معماری OIDC شما طراحی شود و نباید صرفاً به «Session فعلی Browser» اکتفا کرد.


# نکات امنیتی مهم

قبل از Production این موارد را بررسی کنید:

۱. URLهای Logout را Whitelist کنید

هیچ URL دلخواهی را قبول نکنید.

۲. Open Redirect ایجاد نکنید

Redirect مقصد باید از Configuration معتبر بیاید.

۳. iframe Policy را بررسی کنید

CSP و frame-ancestors باید با معماری هماهنگ باشند.

۴. Cookie Policy را بررسی کنید

SameSite و Secure و HttpOnly را بررسی کنید.

۵. Session را واقعاً Revoked کنید

صرفاً نمایش صفحه Logout کافی نیست.

۶. Session Mapping داشته باشید

رابطه بین OP Session و Local Session باید مشخص باشد.

۷. Token Lifecycle را جداگانه مدیریت کنید

Logout Session الزاماً تمام Tokenها را بی‌اعتبار نمی‌کند.


# چک‌لیست Front-Channel Logout

قبل از انتشار سیستم:

  • [ ] برای هر RP یک Front-Channel Logout URI ثبت شده است.
  • [ ] URLها از Client Registration معتبر دریافت می‌شوند.
  • [ ] Open Redirect وجود ندارد.
  • [ ] Logout Page به RPهای ثبت‌شده iframe ارسال می‌کند.
  • [ ] Browser Cookie Policy بررسی شده است.
  • [ ] SameSite مناسب تنظیم شده است.
  • [ ] HTTPS فعال است.
  • [ ] CSP بررسی شده است.
  • [ ] frame-ancestors با معماری هماهنگ است.
  • [ ] Session Mapping وجود دارد.
  • [ ] Local Session واقعاً Revoked می‌شود.
  • [ ] Token Lifecycle جداگانه مدیریت شده است.
  • [ ] رفتار Browserهای مختلف تست شده است.
  • [ ] RPهای Offline یا Unavailable در نظر گرفته شده‌اند.

# سوالات متداول

Front-Channel Logout چیست؟

مکانیزمی در OpenID Connect است که در آن Identity Provider از طریق Browser کاربر به Relying Partyها اطلاع می‌دهد که Logout باید انجام شود.

آیا Front-Channel Logout از iframe استفاده می‌کند؟

در معماری استاندارد Front-Channel Logout، iframe یکی از مکانیزم‌های اصلی برای بارگذاری Logout URIهای RPها است.

آیا Front-Channel Logout به Cookie وابسته است؟

ممکن است باشد؛ زیرا RP باید Session محلی را شناسایی و مدیریت کند و Browser Policy می‌تواند روی ارسال Cookie اثر بگذارد.

Back-Channel بهتر است یا Front-Channel؟

این دو برای مسیرهای ارتباطی متفاوت طراحی شده‌اند. Front-Channel از Browser استفاده می‌کند، در حالی که Back-Channel ارتباط Server-to-Server دارد. انتخاب بین آنها باید بر اساس معماری، نیاز به Browser، مدیریت Session و الزامات امنیتی سیستم انجام شود.

آیا Front-Channel Logout همان RP-Initiated Logout است؟

خیر.

در RP-Initiated Logout، RP فرآیند Logout را شروع می‌کند؛ اما Front-Channel Logout مکانیزمی برای اطلاع‌رسانی Logout از OP به RP از طریق Browser است.

آیا OIDC Session Management همان Front-Channel Logout است؟

خیر.

OIDC Session Management برای بررسی وضعیت Session در OP طراحی شده است، در حالی که Front-Channel Logout مکانیزم انتقال Logout به RPها از طریق Browser است.


# جمع‌بندی

Front-Channel Logout یکی از روش‌های مهم برای مدیریت Logout در معماری‌های چنداپلیکیشنی OpenID Connect است.

در این روش:


User

 ↓

Identity Provider

 ↓

Logout Page

 ↓

Browser

 ↓

RP Logout Endpoint

 ↓

Local Session

 ↓

Revoke

برخلاف Back-Channel Logout، Browser نقش اصلی را در انتقال درخواست Logout به RPها دارد.

این موضوع در عین اینکه امکان Logout هماهنگ چند اپلیکیشن را فراهم می‌کند، محدودیت‌هایی نیز ایجاد می‌کند؛ از جمله:

  • Cookie Policy
  • SameSite
  • Third-Party Context
  • iframe restrictions
  • CSP
  • Browser Privacy

بنابراین در یک معماری SSO حرفه‌ای، باید Front-Channel Logout را صرفاً به‌عنوان یک Redirect ساده در نظر نگیریم.

ارتباط بین:


Identity Provider

        ↓

OP Session

        ↓

Browser

        ↓

RP

        ↓

Local Session

باید از ابتدا به‌صورت صحیح طراحی شود.

همچنین Front-Channel Logout، Back-Channel Logout، RP-Initiated Logout و OIDC Session Management چهار مفهوم متفاوت هستند و شناخت تفاوت آنها برای طراحی یک سیستم SSO قابل اعتماد ضروری است.

نظرات (0)

نظرات پس از تأیید مدیر نمایش داده می‌شوند

هنوز نظری ثبت نشده است؛ اولین نفر باشید!

مقالات مرتبط

ساخت CMS با Laravel 12؛ آموزش ساخت سیستم مدیریت محتوا از صفر

ساخت CMS با Laravel 12؛ آموزش ساخت سیستم مدیریت محتوا از صفر

۲۴ دقیقه
ساخت فروشگاه اینترنتی با Laravel 12؛ آموزش پروژه‌محور از صفر تا طراحی هسته فروشگاه

ساخت فروشگاه اینترنتی با Laravel 12؛ آموزش پروژه‌محور از صفر تا طراحی هسته فروشگاه

۲۲ دقیقه
ساخت Marketplace با Laravel؛ آموزش طراحی فروشگاه چندفروشندگی

ساخت Marketplace با Laravel؛ آموزش طراحی فروشگاه چندفروشندگی

۲۲ دقیقه
مدیریت Queueهای سنگین در Laravel؛ آموزش پردازش کارهای طولانی

مدیریت Queueهای سنگین در Laravel؛ آموزش پردازش کارهای طولانی

۲۲ دقیقه