Skip to main content

Добавление ролей

Теперь добавим scopes в токен. Даже просто добавление списка ролей оказалось той еще задачей. Во многих инструкциях будет сказано, что настройка маппера в Keycloak Admin Console -> ваш realm → Clients → ваш клиент -> Вкладка Mappers. Но это не так. Пример настройки для получения ролей:

  • Перейди в Client Scopes: Твой realm → Clients → выбери своего клиента → вкладка Client scopes → кликни на дедикейтед скоп *-dedicated (например, my-client-dedicated).
  • Открой вкладку Mappers.
  • Нажми Configure a new mapper и выбери By configuration.
  • Выбери тип маппера: В выпадающем списке выбери User Realm Role.
  •     Вот это ключевой момент: использование предустановленного типа, а не создание своего, гарантирует корректную внутреннюю структуру.
  • Проверь настройки (они должны заполниться автоматически):
  •     Name: Оставь realm roles (или любое другое).
  •     Token Claim Name: Убедись, что здесь realm_access . Это единственное правильное имя поля.
  •     Add to userinfo: Убедись, что переключатель установлен в ON.
  •     Add to access token / Add to ID token: Можно оставить OFF, если роли не нужны в самих JWT токенах.
  • Сохрани маппер (кнопка Save).

 

async def get_current_user_roles(request: Request) -> Optional[dict]:
    """Извлечение ролей"""
    access_token = request.cookies.get("access_token")
    if not access_token:
        return []
    try:
        claims = jwt.get_unverified_claims(access_token)
        roles = claims.get("realm_access", {}).get("roles", [])
        return roles
    except Exception:
        return []
...
@app.get("/", response_class=HTMLResponse)
async def simpleauth(request: Request):
    user = await get_current_user_from_cookie(request)
    if not user:
        login_url = get_login_url()
        html_content = f'<!DOCTYPE html><html><body><a href="{login_url}"><button>Авторизация</button></a></body></html>'
    else:
        roles = await get_current_user_roles(request)
        html_content = f'''<!DOCTYPE html><html><body><a href="/logout"><button>Выход</button></a>
        <p>Доступные ключи: {user.keys()}</p>
        <p>Доступные роли: {roles}</p>
        </body></html>'''
    return HTMLResponse(content=html_content, status_code=200)