Skip to content

Провайдер аутентификации KeyCloak

Описание

Провайдер аутентификации Keycloak использует библиотеку python-keycloak для взаимодействия с сервером Keycloak. В процессе аутентификации провайдер аутентификации Keycloak перенаправляет пользователя на страницу аутентификации Keycloak.

После успешной аутентификации Keycloak перенаправляет пользователя обратно в Syncmaster с кодом авторизации. Затем провайдер аутентификации Keycloak обменивает код авторизации на токен доступа и использует его для получения информации о пользователе с сервера Keycloak. Если пользователь не найден в базе данных Syncmaster, провайдер аутентификации Keycloak создает его. Наконец, провайдер аутентификации Keycloak возвращает пользователя с токеном доступа.

Вы можете ознакомиться со схемой взаимодействия ниже.

Схема взаимодействия

sequenceDiagram
participant "Клиент (Пользователь из браузера)" as Client
participant "Syncmaster"
participant "Keycloak"

Client ->> Syncmaster : Запрос на конечную точку, требующую аутентификации (/v1/users)

Syncmaster --x Client: Перенаправление на URL-адрес входа в Keycloak (если нет токена доступа)

Client ->> Keycloak : Обратное перенаправление на страницу входа Keycloak
alt Успешный вход
Client ->> Keycloak : Вход с логином и паролем
else Login failed
Keycloak --x Client: Отображение ошибки (401 Неавторизован)
end

Keycloak ->> Client : Перенаправление в Syncmaster на конечную точку обратного вызова с кодом
Client ->> Syncmaster : Запрос обратного вызова на /v1/auth/callback с кодом
Syncmaster->> Keycloak : Обмен кода на токен доступа
Keycloak ->> Syncmaster : Возврат JWT токена
Syncmaster ->> Client : Установка JWT токена в браузере пользователя в куках и перенаправление на /v1/users

Client ->> Syncmaster : Перенаправление на /v1/users
Syncmaster ->> Syncmaster : Получение информации о пользователе из JWT токена и проверка пользователя во внутренней базе данных сервера
Syncmaster ->> Syncmaster : Создание пользователя во внутренней базе данных сервера, если не существует
Syncmaster ->> Client: Возврат запрошенных данных

alt Успешный случай
Client ->> Syncmaster : Запрос данных с JWT токеном
Syncmaster ->> Syncmaster : Получение информации о пользователе из JWT токена и проверка пользователя во внутренней базе данных сервера
Syncmaster ->> Syncmaster : Создание пользователя во внутренней базе данных сервера, если не существует
Syncmaster ->> Client: Возврат запрошенных данных

else Access token is expired
Syncmaster ->> Keycloak : Получение нового JWT токена через токен обновления
Keycloak ->> Syncmaster : Возврат нового JWT токена
Syncmaster ->> Syncmaster : Получение информации о пользователе из JWT токена и проверка пользователя во внутренней базе данных сервера
Syncmaster ->> Syncmaster : Создание пользователя во внутренней базе данных сервера, если не существует
Syncmaster ->> Client: Возвращает запрошенные данные и устанавливает новый токен JWT в браузере пользователя в файлах cookie.
else Refresh token is expired
Syncmaster --x Client: Перенаправление на URL-адрес входа в Keycloak
end

deactivate Client

Базовая конфигурация

Bases: BaseModel

Settings for KeycloakAuthProvider.

Examples

.. code-block:: yaml :caption: config.yml

auth:
    provider: syncmaster.server.providers.auth.keycloak_provider.KeycloakAuthProvider
    keycloak:
        api_url: http://localhost:8080/auth
        client_id: my_keycloak_client
        client_secret: keycloak_client_secret
        realm_name: my_realm
        ui_callback_url: http://localhost:8000/auth/realms/my_realm/protocol/openid-connect/auth
        verify_ssl: false
        scope: openid
    cookie:
        secret_key: cookie_secret
Source code in syncmaster/server/settings/auth/keycloak.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
class KeycloakAuthProviderSettings(BaseModel):
    """Settings for KeycloakAuthProvider.

    Examples
    --------

    .. code-block:: yaml
        :caption: config.yml

        auth:
            provider: syncmaster.server.providers.auth.keycloak_provider.KeycloakAuthProvider
            keycloak:
                api_url: http://localhost:8080/auth
                client_id: my_keycloak_client
                client_secret: keycloak_client_secret
                realm_name: my_realm
                ui_callback_url: http://localhost:8000/auth/realms/my_realm/protocol/openid-connect/auth
                verify_ssl: false
                scope: openid
            cookie:
                secret_key: cookie_secret
    """

    keycloak: KeycloakSettings = Field(
        description="Keycloak settings",
    )
    cookie: KeycloakCookieSettings = Field(
        description="Keycloak cookie settings",
    )

Bases: BaseModel

Source code in syncmaster/server/settings/auth/keycloak.py
15
16
17
18
19
20
21
22
class KeycloakSettings(BaseModel):
    api_url: HttpUrl = Field(description="Keycloak API URL")
    client_id: str = Field(description="Keycloak client ID")
    client_secret: SecretStr = Field(description="Keycloak client secret")
    realm_name: str = Field(description="Keycloak realm name")
    ui_callback_url: str = Field(description="SyncMaster UI auth callback endpoint")
    verify_ssl: bool = Field(default=True, description="Verify SSL certificates")
    scope: str = Field(default="openid", description="Keycloak scope")

Bases: BaseModel

Settings related to JWT tokens.

Examples

.. code-block:: yaml :caption: config.yml

auth:
    access_key:
        secret_key: jwt_secret
        expire_seconds: 3600  # 1 hour
Source code in syncmaster/server/settings/auth/jwt.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class JWTSettings(BaseModel):
    """Settings related to JWT tokens.

    Examples
    --------

    .. code-block:: yaml
        :caption: config.yml

        auth:
            access_key:
                secret_key: jwt_secret
                expire_seconds: 3600  # 1 hour
    """

    secret_key: SecretStr = Field(
        description=textwrap.dedent(
            """
            Secret key for signing JWT tokens.

            Can be any string. It is recommended to generate random value for every application instance, e.g.:

            .. code:: shell

                pwgen 32 1
            """,
        ),
    )
    security_algorithm: str = Field(
        default="HS256",
        description=textwrap.dedent(
            """
            Algorithm used for signing JWT tokens.

            See `pyjwt <https://pyjwt.readthedocs.io/en/latest/algorithms.html>`_
            documentation.
            """,
        ),
    )
    expire_seconds: int = Field(
        default=10 * 60 * 60,
        description="Token expiration time, in seconds",
    )

Keycloak