> ## Content Index
> Fetch the complete content index at: https://arabroot.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# كيف تحمي أي تطبيق ويب بصفحة دخول authentik عبر Forward Auth
- URL: https://arabroot.io/articles/حماية-أي-تطبيق-باستخدام-authentik-forward-auth/
- Published: 2026-09-24T09:10:00.000Z
- Updated: 2026-10-04T20:05:48.000Z
- Description: لديك أداة داخلية لا تحتوي على صفحة دخول؟ يمكنك أن تضع أمامها صفحة دخول authentik مع المصادقة الثنائية، دون أي تعديل على التطبيق نفسه.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, الأمن والدخول الموحد, الاستضافة الذاتية, authentik

لنفرض أن لديك على السيرفر لوحة Uptime Kuma ولوحة Prometheus وواجهة لقاعدة البيانات Database وأداة داخلية كتبها فريقك على عجل، فسوف تجد أن معظمها لا يملك نظام تسجيل دخول Login أصلاً، أو يملك نظاماً ضعيفاً بكلمة مرور واحدة يتشاركها الجميع، وتركها مكشوفة على الإنترنت يعني أن أي شخص يعرف العنوان يستطيع فتحها. والحل الأول الذي يخطر على البال هو أن تضع أمامها Basic Auth في الـ Reverse Proxy، وهو ما تفعله قائمة الوصول Access List في [دليل NPM](https://arabroot.io/articles/nginx-proxy-manager-%D9%86%D8%B7%D8%A7%D9%82%D8%A7%D8%AA-%D9%88%D8%B4%D9%87%D8%A7%D8%AF%D8%A7%D8%AA-tls/)، ولكن هذا الحل يفشل عندما يكبر الفريق، والسبب أن Basic Auth لا يعرف من هو المستخدم، فلا يفرض عليه مصادقة ثنائية Two-Factor Authentication ولا يسجل من دخل ومتى، وعندما يغادر موظف الشركة يجب عليك أن تغير كلمة المرور على كل أداة وتوزعها من جديد على كل من بقي، وإذا نسيت أداة واحدة فسوف يبقى له باب مفتوح دون أن تنتبه.

📌

في 7 مايو 2021 اكتشفت شركة Colonial Pipeline، التي تدير خط وقود يمتد أكثر من 5,500 ميل على الساحل الشرقي الأمريكي، أن مجموعة DarkSide شفرت أنظمتها الإدارية IT ببرنامج فدية Ransomware، فأوقفت ضخ الوقود في الخط كله احتياطاً ودفعت فدية قدرها 4.4 مليون دولار. وفي جلسة [مجلس الشيوخ الأمريكي في 8 يونيو 2021](https://www.govinfo.gov/content/pkg/CHRG-117shrg46569/pdf/CHRG-117shrg46569.pdf?ref=arabroot.io) قال الرئيس التنفيذي Joseph Blount إن المهاجم دخل عبر حساب VPN قديم Legacy لم يكن يفترض أن يبقى مستخدماً، وإن هذا الحساب كان يحميه عامل واحد فقط هو كلمة مرور معقدة دون مصادقة متعددة العوامل Multi-Factor Authentication. والدرس هنا أن كلمة المرور وحدها لا تحمي حتى لو كانت قوية، وأن الحسابات التي نسيتها هي أخطر ما في شبكتك، لذلك يجب أن تمر كل أبوابك على مكان واحد يفرض MFA ويغلق الحساب مرة واحدة.

لذلك فالحل الأنسب يختلف بحسب التطبيق، فالتطبيقات التي تدعم OIDC أو SAML، مثل Gitea وOutline وMattermost، اربطها مباشرة عبر OIDC كما في [دليل ربط Gitea مع authentik](https://arabroot.io/articles/%D8%B1%D8%A8%D8%B7-gitea-%D9%85%D8%B9-authentik-%D8%B9%D8%A8%D8%B1-oidc/)، حيث يعرف التطبيق المستخدم ويدير صلاحياته Permissions بنفسه ولا تعتمد الحماية كلها على الـ Reverse Proxy، أما التطبيقات التي لا تدعمهما، وهي موضوع هذا الدليل، فحلها [**Forward Auth**](https://docs.goauthentik.io/add-secure-apps/providers/proxy/forward%5Fauth/?ref=arabroot.io).

والفكرة أن الـ Reverse Proxy قبل أن يمرر أي طلب Request إلى التطبيق يسأل [authentik](https://goauthentik.io/?ref=arabroot.io): هل سجل هذا المستخدم دخوله، وهل يحق له الوصول؟ فإذا لم يكن كذلك حوله إلى صفحة دخول Login Page في authentik، بما فيها من مصادقة ثنائية وسياسات Policies، ثم أعاده إلى التطبيق بعد الدخول، وبالتالي فالتطبيق نفسه لا يتغير ولا يعلم بوجود authentik أصلاً، ولكنه يستطيع إن أراد أن يقرأ اسم المستخدم ومجموعاته Groups من ترويسات HTTP Headers يضيفها الـ Reverse Proxy. وقد يتساءل البعض: لماذا لا أضع هذه الأدوات خلف VPN وأنتهي؟ والإجابة أن VPN يحميها فعلاً، ولكنه يصعب على الفريق الوصول إليها من أي جهاز، ويبقى سؤال من دخل ومتى بلا إجابة، أما Forward Auth فيعطيك صفحة دخول واحدة من المتصفح مع MFA وسجل للأحداث Events، وتستطيع أن تجمع بين الاثنين إذا أردت.

وسوف نناقش في هذا المقال ما يلي:

- كيف يعمل Forward Auth خطوة بخطوة، وما دور الـ outpost المدمج في authentik.
- تشغيل تطبيق تجريبي دون منفذ منشور، ثم إنشاء التطبيق والمزود Provider في authentik وقصر الوصول على مجموعة واحدة.
- الإعداد في Nginx Proxy Manager، ومعه البديلان Traefik وCaddy.
- التحقق من الإعداد، وإعدادات مفيدة في المزود، والنسخ الاحتياطي والتحديث وأشهر المشكلات وحلولها.

## كيف يعمل Forward Auth؟

1. يطلب المستخدم `https://app.example.com/`.
2. يرسل الـ Reverse Proxy طلباً فرعياً Subrequest إلى الـ outpost في authentik على المسار Path `/outpost.goauthentik.io/auth/…`، وفي Nginx يتم ذلك عبر [auth\_request](https://nginx.org/en/docs/http/ngx%5Fhttp%5Fauth%5Frequest%5Fmodule.html?ref=arabroot.io)، وفي Traefik عبر [forwardAuth](https://doc.traefik.io/traefik/reference/routing-configuration/http/middlewares/forwardauth/?ref=arabroot.io)، وفي Caddy عبر [forward\_auth](https://caddyserver.com/docs/caddyfile/directives/forward%5Fauth?ref=arabroot.io).
3. إذا لم توجد جلسة Session صالحة يرد الـ outpost برمز الحالة Status Code رقم 401، وعندها يحول الـ Reverse Proxy المستخدم Redirect إلى `/outpost.goauthentik.io/start`، ومنها إلى صفحة دخول authentik.
4. بعد الدخول وتطبيق سياسات التطبيق، كاشتراط العضوية في مجموعة معينة، يعود المستخدم إلى التطبيق ومعه Cookie خاص بالنطاق Domain.
5. في الطلبات التالية يرد الـ outpost بالرمز 200 مع الترويسات `X-authentik-username` و`X-authentik-email` و`X-authentik-groups`، ويمررها الـ Reverse Proxy إلى التطبيق، ولاحظ أن المجموعات تصل في ترويسة واحدة [يفصل بينها الرمز |](https://docs.goauthentik.io/add-secure-apps/providers/proxy/?ref=arabroot.io).

والـ [**outpost**](https://docs.goauthentik.io/add-secure-apps/outposts/?ref=arabroot.io) هو المكون Component الذي يجيب عن هذه الأسئلة، ويأتي authentik مع [outpost مدمج Embedded Outpost](https://docs.goauthentik.io/add-secure-apps/outposts/embedded/?ref=arabroot.io) يعمل داخل الـ Container المسمى server على المنفذ Port رقم 9000، وهو يكفي لمعظم الحالات فلا تحتاج إلى Container إضافي.

## المتطلبات

- نسخة authentik عاملة على `https://auth.example.com` كما في [دليل تثبيت authentik](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-authentik-%D9%84%D9%84%D8%AF%D8%AE%D9%88%D9%84-%D8%A7%D9%84%D9%85%D9%88%D8%AD%D8%AF/)، وفيها مستخدم ومجموعة، وسوف نستخدم في هذا الدليل المجموعة `engineering`.
- Reverse Proxy، وهو هنا Nginx Proxy Manager كما في [دليل NPM](https://arabroot.io/articles/nginx-proxy-manager-%D9%86%D8%B7%D8%A7%D9%82%D8%A7%D8%AA-%D9%88%D8%B4%D9%87%D8%A7%D8%AF%D8%A7%D8%AA-tls/)، أو Traefik، أو Caddy، ويجب أن يكون الـ Reverse Proxy وauthentik على شبكة Docker مشتركة Shared Network اسمها `proxy`.
- نطاق فرعي Subdomain للتطبيق المحمي Protected App يشير إلى السيرفر، وهو هنا `app.example.com`.
- التطبيق نفسه، وللتجربة سوف نستخدم [traefik/whoami](https://github.com/traefik/whoami?ref=arabroot.io)، وهو سيرفر صغير يعرض كل ترويسات الطلب الذي يصله، فترى بعينك ما يمرره authentik.

## نبدأ بتطبيق تجريبي Demo App

لا تقم بنشر Publish أي منفذ للتطبيق المحمي على السيرفر، والسبب أن أي شخص يستطيع عندها تجاوز الحماية Bypass بطلب المنفذ مباشرة دون أن يمر على الـ Reverse Proxy، لذلك لا نضع `ports` إطلاقاً ونكتفي بضم التطبيق إلى شبكة `proxy`:

```yaml
services:
  whoami:
    image: traefik/whoami:v1.12.0
    container_name: whoami
    restart: unless-stopped
    networks:
      - proxy

networks:
  proxy:
    external: true
```

```bash
mkdir -p /opt/whoami && cd /opt/whoami
docker compose up -d
```

🛑

لا يحمي Forward Auth إلا الطريق الذي يمر عبر الـ Reverse Proxy، فإذا نشرت التطبيق بمنفذ على عنوان السيرفر العام (مثل `ports: "8080:80"`) فسوف يبقى مكشوفاً دون حماية، لذلك تحقق بالأمر `docker ps` أنه لا توجد للتطبيق منافذ منشورة، وراجع إعدادات جدار الحماية Firewall.

## كيف تنشئ التطبيق والمزود Provider في authentik؟

من لوحة الإدارة Admin Interface افتح **Applications ← Applications** واضغط **New Application**، وسوف ينشئ [المعالج Wizard](https://docs.goauthentik.io/add-secure-apps/applications/manage%5Fapps/?ref=arabroot.io) التطبيق والمزود معاً كما يلي:

1. **Application:** الاسم `Whoami`، ويملأ المعالج حقل الـ slug تلقائياً بالقيمة `whoami`.
2. **Choose a Provider:** اختر [**Proxy Provider**](https://docs.goauthentik.io/add-secure-apps/providers/proxy/?ref=arabroot.io).
3. **Configure Provider:**
  - **Authorization Flow:** `default-provider-authorization-implicit-consent`، ومع هذا الخيار لا يطلب authentik موافقة المستخدم Consent في كل مرة، وهذا يناسب تطبيقات الشركة الداخلية.
  - اختر تبويب **Forward auth (single application)**.
  - **External host:** `https://app.example.com`، واكتب العنوان كما يكتبه المستخدم في المتصفح بالضبط مع المنفذ إن لم يكن قياسياً، والسبب أن authentik يطابق الطلب مع التطبيق بهذا الحقل.

![إعداد Proxy Provider في وضع Forward auth single application مع حقل External host](https://arabroot.io/content/images/2026/09/authentik-forward-auth-01-proxy-provider-forward-auth.webp)

المزود في وضع Forward auth لتطبيق واحد

وهناك [وضعان Modes](https://docs.goauthentik.io/add-secure-apps/providers/proxy/forward%5Fauth/?ref=arabroot.io) لـ Forward Auth، ففي وضع **single application** تخصص مزوداً لكل نطاق فرعي، فيكون لكل تطبيق جلسته وسياساته وربطه بالمجموعات، وفي وضع **domain level** يحمي مزود واحد كل النطاقات الفرعية تحت `example.com` بجلسة مشتركة، حيث تحدد فيه [عنوان المصادقة Authentication URL ونطاق الـ Cookie](https://docs.goauthentik.io/add-secure-apps/providers/proxy/create-proxy-provider/?ref=arabroot.io) Cookie domain بدل External host، ويحول الـ Reverse Proxy المستخدم إلى عنوان authentik نفسه بدل نطاق التطبيق. والوضع الثاني أسهل عندما تكثر التطبيقات، ولكنه لا يستطيع أن يفرض سياسة مختلفة لكل تطبيق، أي أن من يدخل واحداً منها يدخلها كلها، لذلك ابدأ بوضع single application.

1. **Configure Bindings:** اضغط **Bind existing policy/group/user**، واختر تبويب **Group** ثم المجموعة `engineering`، وبهذا يقتصر دخول التطبيق على أعضائها.

![ربط المجموعة engineering بالتطبيق في خطوة Configure Bindings](https://arabroot.io/content/images/2026/09/authentik-forward-auth-02-group-binding.webp)

قصر الوصول على مجموعة engineering

ثم اضغط **Create Application**. **وتذكر:** إذا لم تضف أي ربط Binding فسوف يدخل التطبيق كل مستخدم في authentik، والسبب أن التطبيق الذي لا يوجد له أي ربط مفتوح لكل من يملك حساباً.

### لا تنس إضافة التطبيق إلى الـ outpost المدمج

المزود وحده لا يعمل حتى يعرف الـ outpost أنه مسؤول عن هذا التطبيق، لذلك افتح **Applications ← Outposts**، ثم افتح **authentik Embedded Outpost** للتعديل، وانقل `Whoami` إلى **Selected Applications** ثم احفظ.

![نافذة Edit Outpost وفيها تطبيق Whoami ضمن التطبيقات المختارة](https://arabroot.io/content/images/2026/09/authentik-forward-auth-03-embedded-outpost-apps.webp)

ربط التطبيق بالـ outpost المدمج

وفي **Advanced settings** للـ outpost نفسه تأكد أن [authentik\_host](https://docs.goauthentik.io/add-secure-apps/outposts/embedded/?ref=arabroot.io) هو العنوان العام Public URL الكامل `https://auth.example.com` وليس اسم النطاق وحده، والسبب أن المستخدم يتوجه إليه لتسجيل الدخول. ويطبق الـ outpost التغييرات خلال ثوان، وسوف ترى في سجل Log الـ Container المسمى server سطراً فيه عبارة `loaded application` واسم النطاق.

## كيف تضبط الحماية في Nginx Proxy Manager؟

أضف في [Nginx Proxy Manager](https://nginxproxymanager.com/?ref=arabroot.io) مضيفاً جديداً Proxy Host بالقيم التالية:

- **Domain Names:** `app.example.com`
- **Scheme:** `http`، **Forward Hostname:** `whoami`، **Forward Port:** `80`
- فعل **Websockets Support** و**Block Common Exploits**.
- من تبويب **SSL** اطلب شهادة Let's Encrypt، وفعل **Force SSL**.

![نافذة Edit Proxy Host في Nginx Proxy Manager وفيها النطاق والوجهة whoami على المنفذ 80](https://arabroot.io/content/images/2026/09/authentik-forward-auth-04-npm-proxy-host.webp)

المضيف في NPM يوجه الطلبات إلى الـ Container الخاص بالتطبيق

ثم افتح تبويب [الإعدادات المتقدمة Advanced Settings](https://nginxproxymanager.com/advanced-config/?ref=arabroot.io)، وهو في NPM 2.16 رمز الترس، وفي الواجهة القديمة اسمه Advanced، والصق فيه الإعداد التالي المبني على [مثال Nginx في توثيق authentik](https://docs.goauthentik.io/add-secure-apps/providers/proxy/server%5Fnginx/?ref=arabroot.io) Documentation، مع تغيير `authentik-server-1` إلى اسم الـ Container الخاص بـ server لديك كما يظهر في `docker ps`:

```nginx
# ترويسات authentik كبيرة نسبياً
proxy_buffers 8 16k;
proxy_buffer_size 32k;

# لا تضف منفذ NPM الداخلي إلى التحويلات
port_in_redirect off;

# احتفظ بترويسة Host كما أرسلها المتصفح (مع المنفذ إن وجد)
set $ak_http_host $http_host;
if ($ak_http_host = "") {
    set $ak_http_host $host;
}

location / {
    proxy_pass          $forward_scheme://$server:$port;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
    proxy_http_version 1.1;

    # الترويسات التي يضيفها NPM في كتلته الافتراضية
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;

    # اسأل authentik قبل تمرير الطلب
    auth_request     /outpost.goauthentik.io/auth/nginx;
    error_page       401 = @goauthentik_proxy_signin;
    auth_request_set $auth_cookie $upstream_http_set_cookie;
    add_header       Set-Cookie $auth_cookie;

    # مرر هوية المستخدم إلى التطبيق
    auth_request_set $authentik_username $upstream_http_x_authentik_username;
    auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
    auth_request_set $authentik_entitlements $upstream_http_x_authentik_entitlements;
    auth_request_set $authentik_email $upstream_http_x_authentik_email;
    auth_request_set $authentik_name $upstream_http_x_authentik_name;
    auth_request_set $authentik_uid $upstream_http_x_authentik_uid;

    proxy_set_header X-authentik-username $authentik_username;
    proxy_set_header X-authentik-groups $authentik_groups;
    proxy_set_header X-authentik-entitlements $authentik_entitlements;
    proxy_set_header X-authentik-email $authentik_email;
    proxy_set_header X-authentik-name $authentik_name;
    proxy_set_header X-authentik-uid $authentik_uid;
}

# مسارات الـ outpost يجب أن تعمل دون تسجيل دخول
location /outpost.goauthentik.io {
    proxy_pass              http://authentik-server-1:9000/outpost.goauthentik.io;
    proxy_set_header        Host $ak_http_host;
    proxy_set_header        X-Original-URL $scheme://$ak_http_host$request_uri;
    add_header              Set-Cookie $auth_cookie;
    auth_request_set        $auth_cookie $upstream_http_set_cookie;
    proxy_pass_request_body off;
    proxy_set_header        Content-Length "";
}

# عند الرد بـ 401 ابدأ تسجيل الدخول
location @goauthentik_proxy_signin {
    internal;
    add_header Set-Cookie $auth_cookie;
    return 302 /outpost.goauthentik.io/start?rd=$scheme://$ak_http_host$request_uri;
}
```

![تبويب Custom Nginx Configuration في NPM وفيه إعداد auth_request الخاص بـ authentik](https://arabroot.io/content/images/2026/09/authentik-forward-auth-05-npm-advanced.webp)

الإعداد المتقدم في NPM، والسطر الأول فيه لا يلزم إلا على منفذ غير قياسي

في الإعداد أعلاه لاحظ التالي:

- عندما يجد NPM الكتلة Block `location /` في الإعداد المتقدم فإنه يستخدمها مكان كتلته الافتراضية، و`$forward_scheme` و`$server` و`$port` متغيرات Variables يملؤها NPM من تبويب Details، فلا تكتب اسم التطبيق ومنفذه مرتين.
- لأن كتلتنا تحل مكان كتلة NPM الافتراضية فهي لا ترث ترويساتها، لذلك أضفنا `Host` و`X-Forwarded-Proto` و`X-Forwarded-For` و`X-Real-IP` بأنفسنا، وبدونها يصل إلى التطبيق `Host: whoami` بدل نطاقه الحقيقي ولا يعرف عنوان الزائر ولا أن الطلب جاء عبر HTTPS، وهذا يكسر التطبيقات التي تبني روابطها من الطلب أو تتحقق من CSRF.
- ترويسة `Host` التي نرسلها إلى الـ outpost هي التي يطابق بها authentik الطلب مع حقل External host في المزود، لذلك يجب أن تطابقه حرفياً.
- يجب أن يكون NPM وauthentik على شبكة `proxy` نفسها حتى يصل NPM إلى `authentik-server-1` باسمه.

**تحذير:** لا تعتمد على قائمة الوصول Access List في تبويب Details مع هذا الإعداد، والسبب أن NPM يضع قواعدها داخل كتلة `location /` الافتراضية التي استبدلناها، فلا تطبق إطلاقاً حتى لو اخترتها. وإذا أردت أن تجمع بين قيد عناوين IP وauthentik فاتبع الطريقة الثانية في [توثيق authentik](https://docs.goauthentik.io/add-secure-apps/providers/proxy/server%5Fnginx/?ref=arabroot.io): ضع في الإعداد المتقدم كتلتي الـ outpost و`@goauthentik_proxy_signin` فقط، ثم أضف من تبويب Custom Locations المسار `/` بالوجهة نفسها وضع في إعداده سطور `auth_request` والترويسات دون `location` ودون `proxy_pass`، فيولد NPM الكتلة بنفسه مع ترويساته وقواعد قائمة الوصول، وعندها يجب أن يرد العنوان الممنوع بالرمز 403 حتى مع جلسة authentik صالحة.

## وإذا كنت تستخدم Traefik

في Traefik نعرف الحماية على الـ Container الخاص بـ authentik على شكل middleware من نوع `forwardAuth`، ثم نضيفها إلى أي router كما في [توثيق authentik لـ Traefik](https://docs.goauthentik.io/add-secure-apps/providers/proxy/server%5Ftraefik/?ref=arabroot.io)، لذلك أضف الـ labels التالية إلى خدمة `server` في ملف authentik، وضم الخدمة إلى شبكة Traefik:

```yaml
    labels:
      traefik.enable: "true"
      # واجهة authentik نفسها
      traefik.http.routers.authentik.rule: Host(`auth.example.com`)
      traefik.http.routers.authentik.entrypoints: websecure
      traefik.http.routers.authentik.tls.certresolver: letsencrypt
      traefik.http.routers.authentik.service: authentik
      # مسارات الـ outpost على نطاق التطبيق المحمي (router لكل تطبيق)
      traefik.http.routers.app-outpost.rule: Host(`app.example.com`) && PathPrefix(`/outpost.goauthentik.io/`)
      traefik.http.routers.app-outpost.entrypoints: websecure
      traefik.http.routers.app-outpost.tls.certresolver: letsencrypt
      traefik.http.routers.app-outpost.service: authentik
      traefik.http.services.authentik.loadbalancer.server.port: "9000"
      traefik.http.middlewares.authentik.forwardauth.address: http://authentik-server-1:9000/outpost.goauthentik.io/auth/traefik
      traefik.http.middlewares.authentik.forwardauth.trustForwardHeader: "true"
      traefik.http.middlewares.authentik.forwardauth.authResponseHeaders: X-authentik-username,X-authentik-groups,X-authentik-entitlements,X-authentik-email,X-authentik-name,X-authentik-uid,X-authentik-jwt,X-authentik-meta-jwks,X-authentik-meta-outpost,X-authentik-meta-provider,X-authentik-meta-app,X-authentik-meta-version
```

ثم أضف هذه الـ labels إلى التطبيق المحمي:

```yaml
    labels:
      traefik.enable: "true"
      traefik.http.routers.whoami.rule: Host(`app.example.com`)
      traefik.http.routers.whoami.entrypoints: websecure
      traefik.http.routers.whoami.tls.certresolver: letsencrypt
      traefik.http.routers.whoami.middlewares: authentik@docker
```

والشرط المهم هنا أن تذهب طلبات `/outpost.goauthentik.io/` على نطاق التطبيق إلى authentik لا إلى التطبيق، وهذا عمل router `app-outpost`، وقاعدته Rule أطول من قاعدة router التطبيق فيعطيها Traefik الأولوية Priority تلقائياً، والسبب أن الأولوية الافتراضية في Traefik هي طول القاعدة. والأمثلة مكتوبة لـ Traefik v3، وأحدث إصدار منه وقت الكتابة هو [3.7.13](https://github.com/traefik/traefik/releases/tag/v3.7.13?ref=arabroot.io).

## وإذا كنت تستخدم Caddy

```nginx
app.example.com {
    route {
        # مسارات الـ outpost تذهب إلى authentik دائمًا
        reverse_proxy /outpost.goauthentik.io/* http://authentik-server-1:9000

        # اسأل authentik قبل كل طلب
        forward_auth http://authentik-server-1:9000 {
            uri /outpost.goauthentik.io/auth/caddy
            copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Entitlements X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
            trusted_proxies private_ranges
        }

        reverse_proxy whoami:80
    }
}
```

في الإعداد أعلاه لاحظ أن Caddy [يعيد ترتيب التوجيهات Directives](https://caddyserver.com/docs/caddyfile/directives/route?ref=arabroot.io) افتراضياً بحسب ترتيب ثابت عنده، لذلك نحتاج كتلة `route`، فهي تضمن تنفيذ `forward_auth` قبل `reverse_proxy` الأخير. واكتب أسماء الترويسات في `copy_headers` بحالة الأحرف Capitalization كما هي تماماً، والسبب أنها تصل فارغة إذا اختلفت، والمثال الأصلي في [توثيق authentik لـ Caddy](https://docs.goauthentik.io/add-secure-apps/providers/proxy/server%5Fcaddy/?ref=arabroot.io).

## كيف تتحقق من نجاح الإعداد؟

افتح `https://app.example.com/` في نافذة خاصة Private Window، وسوف يحولك الـ Reverse Proxy فوراً إلى authentik مع عبارة «Log in to continue to Whoami» كما في الصورة التالية:

![صفحة دخول authentik مع عبارة Log in to continue to Whoami](https://arabroot.io/content/images/2026/09/authentik-forward-auth-06-login-redirect.webp)

التحويل التلقائي إلى authentik عند فتح التطبيق دون جلسة

ادخل بحساب من مجموعة `engineering`، ومعه رمز TOTP إن كانت المصادقة الثنائية مفروضة، وسوف تعود إلى التطبيق ويعرض whoami الترويسات التي أضافها authentik:

![مخرجات whoami وفيها ترويسات X-Authentik-Username وX-Authentik-Email وX-Authentik-Groups](https://arabroot.io/content/images/2026/09/authentik-forward-auth-07-whoami-headers.webp)

التطبيق يستقبل هوية المستخدم في ترويسات X-Authentik-\*

أما الحساب الذي لا ينتمي إلى المجموعة فيرفضه authentik، حتى لو كان حساب مدير authentik نفسه:

![رسالة Permission denied من authentik لحساب akadmin لأنه ليس عضواً في المجموعة المسموح لها](https://arabroot.io/content/images/2026/09/authentik-forward-auth-08-permission-denied.webp)

يسري ربط المجموعة على الجميع، بمن فيهم المديرون

ومن سطر الأوامر Command Line، فالطلب الذي لا يحمل Cookie يجب أن يرد بتحويل 302 إلى `/outpost.goauthentik.io/start` لا بمحتوى التطبيق:

```bash
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' https://app.example.com/
```

ولتسجيل الخروج Logout استخدم `https://app.example.com/outpost.goauthentik.io/sign_out`، وإن كانت واجهة التطبيق تسمح فضعه فيها رابطاً، ولاحظ أن هذا الرابط [ينهي كل جلسات المستخدم في الـ outpost](https://docs.goauthentik.io/add-secure-apps/providers/proxy/?ref=arabroot.io)، أي في كل التطبيقات التي يحميها الـ outpost نفسه وليس في هذا التطبيق وحده.

## إعدادات في المزود سوف تحتاجها لاحقاً

- [**Unauthenticated Paths**](https://docs.goauthentik.io/add-secure-apps/providers/proxy/?ref=arabroot.io) (ضمن Advanced protocol settings): تعبيرات نمطية Regex لمسارات تستثنيها من الحماية، مثل واجهة API يستدعيها نظام آخر أو webhook، ومثالها `^/api/.*`، وكل سطر تعبير مستقل. واجعل الاستثناءات أضيق ما يمكن، والسبب أن كل مسار تستثنيه مفتوح لكل الإنترنت، ولاحظ أن التعبير الذي فيه خطأ في الكتابة يتجاهله authentik ويكتب تحذيراً في سجل الـ outpost فقط، فيبقى المسار محمياً ولا تعرف السبب حتى تقرأ السجل.
- **Token validity:** مدة صلاحية الجلسة Session Validity في التطبيق، وهي 24 ساعة افتراضياً، وبعدها يمر المستخدم على authentik من جديد، وغالباً لن يحتاج إلى كلمة مرور إذا كانت جلسته في authentik ما زالت سارية.
- [**Send HTTP-Basic Authentication**](https://docs.goauthentik.io/add-secure-apps/providers/proxy/header%5Fauthentication/?ref=arabroot.io)**:** للتطبيقات التي لا تقبل إلا Basic Auth، حيث يرسل authentik اسم مستخدم وكلمة مرور يأخذهما من خصائص Attributes في حساب المستخدم أو مجموعته، وإذا لم يجد خاصية اسم المستخدم أرسل بريده بدلاً منه، وتضيف أنت إلى إعداد Nginx سطري `Authorization` المذكورين في [توثيق authentik](https://docs.goauthentik.io/add-secure-apps/providers/proxy/server%5Fnginx/?ref=arabroot.io).
- بعض التطبيقات مثل Grafana تنشئ المستخدم تلقائياً من الترويسة `X-authentik-username`، وهذا ما يسمى وضع [Auth Proxy](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/auth-proxy/?ref=arabroot.io)، ولا تقم بتفعيله إلا إذا كان الـ Reverse Proxy هو الطريق الوحيد إلى التطبيق، والسبب أن من يصل إليه مباشرة يستطيع تزوير الترويسة Spoofing والدخول باسم أي مستخدم.

## النسخ الاحتياطي Backup والاستعادة Restore

هذا الإعداد لا يضيف شيئاً إلى ما تنسخه أصلاً، فالمزود والتطبيق وربط الـ outpost كلها في قاعدة بيانات authentik (راجع قسم النسخ الاحتياطي في دليل التثبيت)، وإعداد المضيف في NPM موجود في مجلد بياناته `/data`. ولكن احفظ أيضاً نسخة نصية من الإعداد المتقدم مع ملفات مشروعك، والسبب أنها أسرع طريقة لإعادة بنائه إذا تعطل NPM أو نقلته إلى سيرفر آخر.

## التحديث Upgrade إلى إصدار أحدث

الـ outpost المدمج يتحدث مع authentik تلقائياً، لأنه يعمل داخل الـ Container المسمى server نفسه، أما إذا نشرت [outpost منفصلاً](https://docs.goauthentik.io/add-secure-apps/outposts/?ref=arabroot.io) (`ghcr.io/goauthentik/proxy`) فيجب أن يطابق وسمه Tag [إصدار authentik](https://github.com/goauthentik/authentik/releases/tag/version/2026.8.3?ref=arabroot.io) تماماً، لذلك حدثهما معاً. وعندما تحدث NPM أو Traefik راجع [ملاحظات الإصدار Release Notes](https://github.com/NginxProxyManager/nginx-proxy-manager/releases/tag/v2.16.0?ref=arabroot.io) بحثاً عن تغيير في متغيرات الإعداد المتقدم، وبعد كل تحديث افتح التطبيق المحمي من نافذة خاصة وتأكد أن صفحة الدخول تظهر.

## مشكلات شائعة وحلولها

### خطأ 500 من NPM وفي سجله «auth request unexpected status: 404»

السبب أن الـ outpost لا يعرف هذا النطاق، فإما أن التطبيق غير مضاف إلى الـ outpost المدمج، أو أن External host في المزود لا يطابق ترويسة Host التي يرسلها الـ Reverse Proxy (`http` مكان `https`، أو منفذ ناقص أو زائد). انتظر بضع ثوان بعد حفظ الـ outpost، ثم راجع سجل NPM في `/data/logs/proxy-host-N_error.log`.

### 403 Forbidden من NPM عند التحويل إلى صفحة الدخول

تظهر هذه المشكلة عند العمل عبر HTTP، والسبب أن خيار **Block Common Exploits** في NPM يرفض أي طلب فيه `=http://` في الاستعلام Query String، والرابط `/outpost.goauthentik.io/start?rd=http://…` يطابق هذه القاعدة، أما مع HTTPS فلا تظهر المشكلة لأن القاعدة تبحث عن `http://` فقط. لذلك فالحل أن تعمل عبر HTTPS، ولا تقم بتعطيل الحماية.

### التحويل يفقد المنفذ أو يذهب إلى منفذ خاطئ

عندما يعمل الـ Reverse Proxy على منفذ غير 443 يحول Nginx المسار النسبي Relative Path إلى رابط مطلق Absolute URL دون المنفذ، والحل أن تضيف [absolute\_redirect off;](https://nginx.org/en/docs/http/ngx%5Fhttp%5Fcore%5Fmodule.html?ref=arabroot.io#absolute%5Fredirect) في أعلى الإعداد المتقدم، أما في بيئة الإنتاج Production على المنفذ 443 فلا تحتاج إلى ذلك.

### حلقة تحويل Redirect Loop لا تنتهي بين التطبيق وauthentik

السبب غالباً أن المتصفح لا يحفظ الـ Cookie، فقد يكون الموقع يعمل عبر HTTP وauthentik يضع Cookie آمناً Secure لا يرسله المتصفح إلا عبر HTTPS، أو يكون وقت ساعة السيرفر غير مضبوط Clock Skew، لذلك شغل كل شيء عبر HTTPS وتأكد من مزامنة الوقت Time Sync.

### «upstream sent too big header»

لهذا تحديداً وضعنا السطرين [proxy\_buffers](https://nginx.org/en/docs/http/ngx%5Fhttp%5Fproxy%5Fmodule.html?ref=arabroot.io#proxy%5Fbuffers) و`proxy_buffer_size` في أعلى الإعداد، والسبب أن ترويسات authentik وملفات الـ Cookie التي يضعها أكبر من الحجم الافتراضي في Nginx، فتأكد أنك لم تحذفهما.

### NPM يرفض الحفظ أو يتوقف بعد إعادة التشغيل: «host not found in upstream»

يحل Nginx الاسم `authentik-server-1` Resolve عند تحميل الإعداد، فإذا كان الـ Container الخاص بـ authentik متوقفاً أو غير متصل بشبكة `proxy` فسوف يفشل الإعداد كله، لذلك تحقق بالأمر `docker network inspect proxy` من وجود الـ Containers على الشبكة.

## الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

- Basic Auth في الـ Reverse Proxy يحمي أداة واحدة بكلمة مرور مشتركة، ولكنه لا يعرف المستخدم ولا يفرض MFA، أما Forward Auth فيضع أمام أي تطبيق صفحة دخول authentik بمجموعاتها وسياساتها دون أن يتغير التطبيق.
- التطبيقات التي تدعم OIDC أو SAML اربطها مباشرة، واترك Forward Auth للتطبيقات التي لا تدعمهما.
- لا تنشر أي منفذ للتطبيق المحمي، واربط بالتطبيق مجموعة واحدة على الأقل، ولا تنس إضافته إلى الـ outpost المدمج.
- في NPM أضف ترويسات `Host` و`X-Forwarded-*` بنفسك داخل `location /`، ولا تعتمد على Access List مع هذا الإعداد، وإذا احتجت إليها فاستخدم طريقة Custom Locations.
- ابدأ بوضع single application، ولا تنتقل إلى domain level إلا إذا كانت كل التطبيقات لنفس الأشخاص.

## سجل التحديثات Changelog

- سبتمبر 2026: كتابة الدليل واختباره على authentik 2026.8.3 مع Nginx Proxy Manager 2.16.0.
- أكتوبر 2026: مراجعة الدليل على authentik 2026.8.3 وNginx Proxy Manager 2.16.0: أضفنا إلى إعداد NPM ترويسات `Host` و`X-Forwarded-Proto` و`X-Forwarded-For` و`X-Real-IP` التي كانت تسقط مع استبدال `location /`، ووضحنا أن Access List لا تطبق مع هذا الإعداد وأن طريقة Custom Locations في توثيق authentik تحل ذلك، وصححنا وصف تسجيل الخروج (ينهي كل جلسات المستخدم في الـ outpost)، وأضفنا إعدادات وضع domain level.