Другое

Настройка ABP OIDC с Traefik: Полное руководство

Узнайте, как настроить ABP как OIDC-провайдер идентификации за обратным прокси Traefik. Исправьте проблемы с сохранением cookie с помощью правильной конфигурации URL, SSL и переменных окружения.

Как настроить ABP (ASP.NET Boilerplate) в качестве поставщика идентификации OIDC при развертывании за обратным прокси Traefik? Я столкнулся с проблемами сохранения cookie и потока OIDC при использовании Traefik, в то время как та же настройка работает нормально при запуске обоих сервисов непосредственно в Visual Studio. Конкретно мне нужна помощь в следующем:

  1. Правильная настройка URL и параметров для поставщика идентификации ABP за Traefik
  2. Требования к SSL-сертификатам и настройка HTTPS для сохранения cookie
  3. Настройка потока OIDC в среде с обратным прокси
  4. Настройка Docker Compose для Traefik, поставщика идентификации ABP и основного сервиса
  5. Настройка переменных окружения для URL-адресов клиента OIDC и центра авторизации

Моя текущая настройка включает Traefik в качестве обратного прокси с точками входа HTTP и HTTPS, сервисом идентификации ABP и основным сервисом. При использовании только HTTP браузеры удаляют cookie ABP, но сохраняют cookie сервиса. Мне нужно понять, как настроить поток OIDC, чтобы аутентификация работала правильно в настройке с обратным прокси.

Настройка ABP (ASP.NET Boilerplate) в качестве поставщика OIDC-идентификации за обратным прокси Traefik

Правильная настройка ABP (ASP.NET Boilerplate) в качестве поставщика OIDC-идентификации за обратным прокси Traefik требует корректной конфигурации URL, управления SSL-сертификатами и обработки cookie для обеспечения правильной работы OIDC-потока. Основные проблемы включают сохранение cookie между границами HTTP/HTTPS и обеспечение правильной проксирования всех callback URL через Traefik, при компоненты идентификации ABP могут корректно обнаруживать внешнее имя хоста и схему.

Содержание

Конфигурация URL и настройки

При развертывании ABP за Traefik необходимо настроить как поставщика идентификации ABP, так и OIDC-клиент для использования внешних URL, к которым пользователи и внешние сервисы будут иметь доступ через обратный прокси.

Конфигурация поставщика идентификации ABP

Для сервера идентификации ABP необходимо настроить AppSettings.json для указания правильных URL:

json
{
  "App": {
    "SelfUrl": "https://ваш-домен.com/identity"
  },
  "IdentityServer": {
    "Clients": {
      "DefaultRedirectUri": "https://ваш-домен.com/callback",
      "PostLogoutRedirectUri": "https://ваш-домен.com/signout-callback"
    }
  }
}

Важные замечания:

  • SelfUrl должен соответствовать внешнему URL, через который будет доступен ваш сервер идентификации
  • Все redirect URI должны быть доступны через обратный прокси
  • Используйте HTTPS URL, даже если ваша внутренняя сеть использует HTTP, для обеспечения безопасности cookie

Конфигурация роутера Traefik

Настройте Traefik для правильной маршрутизации запросов к вашему сервису идентификации ABP:

yaml
# docker-compose.yml
traefik:
  labels:
    - "traefik.http.routers.identity.rule=Host(`ваш-домен.com`) && PathPrefix(`/identity`)"
    - "traefik.http.routers.identity.entrypoints=websecure"
    - "traefik.http.routers.identity.tls.certresolver=myresolver"
    - "traefik.http.services.identity.loadbalancer.server.port=5000"

Эта конфигурация обеспечивает:

  • Маршрутизацию запросов к /identity на ваш сервис ABP
  • Использование HTTPS entrypoint
  • Завершение SSL на уровне Traefik
  • Работа бэкенд-сервиса на порту 5000

Конфигурация клиента ABP

Для клиентского приложения, использующего OIDC-поставщик идентификации:

json
{
  "AuthServer": {
    "Authority": "https://ваш-домен.com/identity",
    "RequireHttpsMetadata": true,
    "ClientId": "ваш-id-клиента",
    "ClientSecret": "ваш-секрет-клиента",
    "ResponseType": "code",
    "Scope": "openid profile email",
    "GetClaimsFromUserInfoEndpoint": true,
    "RedirectUri": "https://ваш-домен.com/callback",
    "PostLogoutRedirectUri": "https://ваш-домен.com/signout-callback"
  }
}

Требования к SSL-сертификатам и конфигурация HTTPS

Сохранение cookie и флаг Secure

Основная проблема, с которой вы сталкиваетесь с сохранением cookie, вероятно, связана с тем, что браузеры удаляют cookie при переходе с HTTPS на HTTP. Для решения этой проблемы:

  1. Настройте ABP для использования безопасных cookie:

    json
    {
      "IdentityServer": {
        "CookieOptions": {
          "SecurePolicy": "Always",
          "SameSite": "None"
        }
      }
    }
    
  2. Конфигурация SSL в Traefik:

    yaml
    traefik:
      volumes:
        - /etc/letsencrypt:/letsencrypt
      labels:
        - "traefik.http.routers.identity.tls=true"
        - "traefik.http.routers.identity.tls.options=default@file"
    

Интеграция с Let’s Encrypt

Настройте Traefik для автоматического получения и обновления SSL-сертификатов:

yaml
# docker-compose.yml
traefik:
  command:
    - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
    - "--certificatesresolvers.myresolver.acme.email=ваш-email@example.com"
    - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
  volumes:
    - ./acme.json:/letsencrypt/acme.json
    - /etc/letsencrypt:/letsencrypt

Пользовательские заголовки для ABP

Настройте Traefik для передачи важных заголовков в ABP:

yaml
labels:
  - "traefik.http.middlewares.identity-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
  - "traefik.http.middlewares.identity-headers.headers.customrequestheaders.X-Forwarded-Host=ваш-домен.com"
  - "traefik.http.middlewares.identity-headers.headers.customrequestheaders.X-Forwarded-Prefix=/identity"

Эти заголовки помогают ABP понять внешнюю схему URL и имя хоста, что важно для генерации правильных callback URL.


Конфигурация OIDC-потока в среде с обратным прокси

Валидация redirect URI

ABP IdentityServer валидирует redirect URI против предопределенного списка. Убедитесь, что ваши URL, маршрутизируемые через Traefik, включены:

json
{
  "IdentityServer": {
    "Clients": {
      "AllowedRedirectUris": [
        "https://ваш-домен.com/callback",
        "https://ваш-домен.com/signout-callback"
      ]
    }
  }
}

Конфигурация домена cookie

Настройте параметры домена cookie для работы между поддоменами:

json
{
  "IdentityServer": {
    "CookieOptions": {
      "Domain": "ваш-домен.com",
      "SameSite": "None",
      "SecurePolicy": "Always"
    }
  }
}

Управление сессией

Настройте управление сессией ABP для работы с обратным прокси:

json
{
  "IdentityServer": {
    "Session": {
      "IdleTimeout": "3600s",
      "AbsoluteRefreshInterval": "86400s",
      "SlidingRefreshInterval": "300s",
      "CookieLifetime": "86400s"
    }
  }
}

Discovery endpoint

Убедитесь, что discovery endpoint OpenID Connect ABP правильно работает за Traefik:

bash
# Тестирование endpoint
curl -k https://ваш-домен.com/identity/.well-known/openid-configuration

Ответ должен содержать правильные URL, указывающие на ваш внешний домен:

json
{
  "issuer": "https://ваш-домен.com/identity",
  "authorization_endpoint": "https://ваш-домен.com/identity/connect/authorize",
  "token_endpoint": "https://ваш-домен.com/identity/connect/token",
  "userinfo_endpoint": "https://ваш-домен.com/identity/connect/userinfo",
  "end_session_endpoint": "https://ваш-домен.com/identity/connect/endsession",
  "jwks_uri": "https://ваш-домен.com/identity/.well-known/openid-configuration/jwks",
  "scopes_supported": [
    "openid",
    "profile",
    "email"
  ],
  "response_types_supported": [
    "code",
    "id_token",
    "token id_token"
  ],
  "response_modes_supported": [
    "form_post",
    "query",
    "fragment"
  ]
}

Настройка Docker Compose

Вот полная конфигурация Docker Compose для Traefik, сервера идентификации ABP и клиентского приложения:

yaml
version: '3.8'

services:
  traefik:
    image: traefik:latest
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      - "--certificatesresolvers.myresolver.acme.email=ваш-email@example.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./acme.json:/letsencrypt/acme.json
      - /etc/letsencrypt:/letsencrypt

  abp-identity:
    image: ваш-image-идентификации-abp
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=http://+:5000
      - App__SelfUrl=https://ваш-домен.com/identity
      - IdentityServer__Clients__DefaultRedirectUri=https://ваш-домен.com/callback
      - IdentityServer__Clients__PostLogoutRedirectUri=https://ваш-домен.com/signout-callback
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.identity.rule=Host(`ваш-домен.com`) && PathPrefix(`/identity`)"
      - "traefik.http.routers.identity.entrypoints=websecure"
      - "traefik.http.routers.identity.tls.certresolver=myresolver"
      - "traefik.http.services.identity.loadbalancer.server.port=5000"
      - "traefik.http.middlewares.identity-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
      - "traefik.http.middlewares.identity-headers.headers.customrequestheaders.X-Forwarded-Host=ваш-домен.com"
      - "traefik.http.middlewares.identity-headers.headers.customrequestheaders.X-Forwarded-Prefix=/identity"

  abp-client:
    image: ваш-image-клиента-abp
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=http://+:5001
      - AuthServer__Authority=https://ваш-домен.com/identity
      - AuthServer__ClientId=ваш-id-клиента
      - AuthServer__ClientSecret=ваш-секрет-клиента
      - AuthServer__RedirectUri=https://ваш-домен.com/callback
      - AuthServer__PostLogoutRedirectUri=https://ваш-домен.com/signout-callback
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.client.rule=Host(`ваш-домен.com`) && PathPrefix(`/`)"
      - "traefik.http.routers.client.entrypoints=websecure"
      - "traefik.http.routers.client.tls.certresolver=myresolver"
      - "traefik.http.services.client.loadbalancer.server.port=5001"
      - "traefik.http.middlewares.client-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
      - "traefik.http.middlewares.client-headers.headers.customrequestheaders.X-Forwarded-Host=ваш-домен.com"

volumes:
  acme.json:

Динамическая конфигурация Traefik

Создайте файл traefik.yml для дополнительной конфигурации:

yaml
# traefik.yml
api:
  dashboard: true
  insecure: true

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true
  websecure:
    address: ":443"

providers:
  docker:
    exposedByDefault: false
    network: abp-network

certificatesResolvers:
  myresolver:
    acme:
      email: ваш-email@example.com
      storage: /letsencrypt/acme.json
      tlsChallenge:
        {}

Конфигурация переменных окружения

Переменные окружения для сервера идентификации ABP

Настройте эти переменные окружения для сервера идентификации ABP:

bash
# Конфигурация сервера идентификации
ASPNETCORE_ENVIRONMENT=Production
ASPNETCORE_URLS=http://+:5000

# URL приложения
App__SelfUrl=https://ваш-домен.com/identity
App__BaseUrl=https://ваш-домен.com

# Конфигурация Identity Server
IdentityServer__Authority=https://ваш-домен.com/identity
IdentityServer__RequireHttpsMetadata=true
IdentityServer__SupportedTokens=Jwt

# Конфигурация клиента
IdentityServer__Clients__DefaultClientId=ваш-id-клиента
IdentityServer__Clients__DefaultClientSecret=ваш-секрет-клиента
IdentityServer__Clients__DefaultRedirectUri=https://ваш-домен.com/callback
IdentityServer__Clients__DefaultPostLogoutRedirectUri=https://ваш-домен.com/signout-callback
IdentityServer__Clients__DefaultAllowedGrantTypes=authorization_code,hybrid,client_credentials,implicit
IdentityServer__Clients__DefaultAllowedScopes=openid profile email roles
IdentityServer__Clients__DefaultAllowAccessToAllScopes=false
IdentityServer__Clients__DefaultRequireConsent=false
IdentityServer__Clients__DefaultAllowRememberConsent=true
IdentityServer__Clients__DefaultAlwaysIncludeUserClaimsInIdToken=true
IdentityServer__Clients__DefaultFrontChannelLogoutUri=https://ваш-домен.com/signout-callback
IdentityServer__Clients__DefaultFrontChannelLogoutSessionRequired=true

# Конфигурация cookie
IdentityServer__CookieOptions__SameSite=None
IdentityServer__CookieOptions__SecurePolicy=Always
IdentityServer__CookieOptions__Domain=ваш-домен.com

# Конфигурация сессии
IdentityServer__Session__IdleTimeout=3600s
IdentityServer__Session__AbsoluteRefreshInterval=86400s
IdentityServer__Session__SlidingRefreshInterval=300s
IdentityServer__Session__CookieLifetime=86400s

# Конфигурация CORS
IdentityServer__Cors__PolicyName=DefaultPolicy
IdentityServer__Cors__DefaultAllowedOrigins=https://ваш-домен.com
IdentityServer__Cors__DefaultAllowedMethods=GET,POST,PUT,DELETE,OPTIONS
IdentityServer__Cors__DefaultAllowedHeaders=*,Authorization
IdentityServer__Cors__DefaultExposedHeaders=*,Authorization

Переменные окружения для клиентского приложения ABP

Настройте эти переменные для клиентского приложения:

bash
# Конфигурация клиентского приложения
ASPNETCORE_ENVIRONMENT=Production
ASPNETCORE_URLS=http://+:5001

# Конфигурация аутентификации
AuthServer__Authority=https://ваш-домен.com/identity
AuthServer__ClientId=ваш-id-клиента
AuthServer__ClientSecret=ваш-секрет-клиента
AuthServer__RequireHttpsMetadata=true
AuthServer__GetClaimsFromUserInfoEndpoint=true
AuthServer__SaveTokens=true
AuthServer__ResponseType=code

# Redirect URI
AuthServer__RedirectUri=https://ваш-домен.com/callback
AuthServer__PostLogoutRedirectUri=https://ваш-домен.com/signout-callback

# Scopes
AuthServer__Scope=openid profile email roles

# Конфигурация cookie
AuthServer__CookieOptions__SameSite=None
AuthServer__CookieOptions__SecurePolicy=Always
AuthServer__CookieOptions__Domain=ваш-домен.com

# Challenge Scheme
AuthServer__ChallengeScheme=oidc

# Events
AuthServer__Events__OnRedirectToIdentityProvider=OnRedirectToIdentityProvider
AuthServer__Events__OnCreatingTicket=OnCreatingTicket

# Валидация токена
AuthServer__TokenValidation__NameClaimType=name
AuthServer__TokenValidation__RoleClaimType=role
AuthServer__TokenValidation__ClockSkew=00:05:00

Переменные окружения для Traefik

bash
# Конфигурация Traefik
TRAEFIK_API_DASHBOARD=true
TRAEFIK_API_INSECURE=true
TRAEFIK_PROVIDERS_DOCKER=true
TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT=false
TRAEFIK_ENTRYPOINTS_WEB_ADDRESS=:80
TRAEFIK_ENTRYPOINTS_WEBSECURE_ADDRESS=:443

# Конфигурация SSL-сертификата
TRAEFIK_CERTIFICATERESOLVERS_MYRESOLVER_ACME_EMAIL=ваш-email@example.com
TRAEFIK_CERTIFICATERESOLVERS_MYRESOLVER_ACME_STORAGE=/letsencrypt/acme.json
TRAEFIK_CERTIFICATERESOLVERS_MYRESOLVER_ACME_TLSCHALLENGE=true

# Логирование
TRAEFIK_ACCESSLOG=true
TRAEFIK_ACCESSLOG_FORMAT=json
TRAEFIK_LOG_LEVEL=INFO

Устранение распространенных проблем

Проблемы с сохранением cookie

Проблема: Cookie удаляются при переходе между HTTP и HTTPS.

Решение:

  1. Убедитесь, что все URL используют HTTPS
  2. Настройте SameSite=None и SecurePolicy=Always для cookie
  3. Используйте согласованные настройки домена для всех сервисов
json
{
  "IdentityServer": {
    "CookieOptions": {
      "SameSite": "None",
      "SecurePolicy": "Always",
      "Domain": "ваш-домен.com"
    }
  }
}

Несоответствие redirect URI

Проблема: ABP IdentityServer отклоняет redirect URI, которые не соответствуют настроенным значениям.

Решение:

  1. Убедитесь, что все redirect URI настроены с использованием внешних URL
  2. Включите как HTTP, так и HTTPS версии, если необходимо
  3. Настройте Traefik для сохранения оригинальных заголовков хоста
yaml
# Middleware Traefik для сохранения оригинального хоста
labels:
  - "traefik.http.middlewares.preserve-host.headers.customrequestheaders.X-Forwarded-Host={Host}"

Проблемы с SSL-сертификатами

Проблема: Предупреждения о самоподписанных сертификатах или ошибки валидации сертификата.

Решение:

  1. Используйте Let’s Encrypt для валидных сертификатов
  2. Настройте ABP для правильной валидации сертификатов:
json
{
  "IdentityServer": {
    "RequireHttpsMetadata": true,
    "ValidateAudience": true,
    "ValidateIssuer": true,
    "ValidateLifetime": true,
    "ValidateTokenReplay": true
  }
}

Ошибки OIDC-потока

Проблема: Ошибки “invalid_client” или “invalid_scope” во время OIDC-потока.

Решение:

  1. Проверьте конфигурацию ID и секрета клиента
  2. Убедитесь, что необходимые scopes настроены
  3. Проверьте соответствие redirect URI
bash
# Тестирование token endpoint
curl -X POST https://ваш-домен.com/identity/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=ваш-id-клиента" \
  -d "client_secret=ваш-секрет-клиента" \
  -d "scope=openid"

Лучшие практики

Вопросы безопасности

  1. Всегда используйте HTTPS: Настройте и ABP, и Traefik для принудительного использования HTTPS
  2. Используйте правильные SSL-сертификаты: Сертификаты Let’s Encrypt для production
  3. Правильно настройте CORS: Ограничьте источники до вашего домена
  4. Валидируйте токены: Включите валидацию токенов в конфигурации ABP
  5. Используйте безопасные cookie: Настройте атрибуты SameSite и Secure

Оптимизация производительности

  1. Включите кэширование: Настройте кэширование Traefik для статических ресурсов
  2. Используйте балансировку нагрузки: Настройте несколько бэкенд-инстансов, если необходимо
  3. Оптимизируйте таймауты сессий: Сбалансируйте безопасность и удобство пользователя
  4. Включите сжатие: Настройте middleware Traefik для сжатия
  5. Мониторьте производительность: Настройте health checks и мониторинг

Управление конфигурацией

  1. Используйте переменные окружения: Храните чувствительные данные вне файлов конфигурации
  2. Контролируйте версии конфигураций: Отслеживайте изменения в docker-compose и конфигурациях Traefik
  3. Используйте шаблоны конфигурации: Создавайте переиспользуемые шаблоны для разных окружений
  4. Документируйте конфигурации: Поддерживайте документацию для всех опций конфигурации
  5. Тестируйте конфигурации: Валидируйте конфигурации в staging перед production

Стратегия развертывания

  1. Используйте staging-окружения: Тестируйте конфигурации в staging перед production
  2. Реализуйте health checks: Настройте health checks для всех сервисов
  3. Используйте инструменты оркестрации: Рассмотрите Kubernetes для сложных развертываний
  4. Реализуйте мониторинг: Настройте логирование и мониторинг для всех сервисов
  5. Резервируйте конфигурации: Регулярно создавайте резервные копии важных файлов конфигурации

Заключение

Успешная настройка ABP в качестве OIDC-поставщика идентификации за Traefik требует тщательного внимания к конфигурации URL, управлению SSL-сертификатами и обработке cookie. Ключевые выводы:

  1. Всегда используйте HTTPS для всех внешних URL для обеспечения сохранения cookie и безопасности
  2. Настройте middleware Traefik для передачи правильных заголовков (X-Forwarded-Proto, X-Forwarded-Host) в сервисы ABP
  3. Настройте правильную конфигурацию cookie с SameSite=None и SecurePolicy=Always для сохранения cookie между схемами
  4. Используйте переменные окружения последовательно во всех сервисах для URL и конфигурации аутентификации
  5. Тщательно тестируйте OIDC-поток для обеспечения правильной работы всех redirect URI с обратным прокси

Следуя этим рекомендациям и используя предоставленную конфигурацию Docker Compose, вы должны решить проблемы с сохранением cookie и правильно настроить работу вашего OIDC-поставщика идентификации ABP за обратным прокси Traefik.

Источники

  1. Документация ABP Framework - Конфигурация Identity Server
  2. Документация Traefik - Конфигурация обратного прокси
  3. Спецификация OpenID Connect Core
  4. Документация ASP.NET Core - Аутентификация и авторизация
  5. Документация Docker Compose
  6. Документация Let’s Encrypt
  7. Руководство OWASP по безопасным cookie
Авторы
Проверено модерацией
Модерация