Авторизация AWS AppSync: Полное руководство по OPENID_CONNECT и API_KEY
Узнайте, как правильно настроить AWS AppSync с методами авторизации OPENID_CONNECT и API_KEY. Исправьте проблемы с нулевой идентификацией и разрешите конфликты с помощью нашего полного руководства по устранению неполадок.
Проблема с авторизацией в AWS AppSync: конфликт OPENID_CONNECT и API_KEY
Я столкнулся с проблемой в моем приложении AWS AppSync, где добавление метода авторизации API_KEY нарушило существующие маршруты OPENID_CONNECT. Вот детали:
Описание проблемы
- Мое приложение AWS AppSync корректно работало с авторизацией OPENID_CONNECT
- При добавлении API_KEY в качестве дополнительного метода авторизации, это нарушило существующие маршруты
- В схеме AppSync все маршруты ранее содержали директивы @aws_oidc и @aws_api_key
- После изменений, когда запросы достигают конвейера резолверов:
- идентификатор приходит как null
- заголовок x-api-key вставляется во все маршруты
Попытки решения
- Я пытался удалить @aws_api_key из всех маршрутов и типов, так как мы ранее не использовали API_KEY
- Это привело к ошибкам Unauthorized
Дополнительный контекст
- Я отладил CloudFront Lambda Edge и подтвердил, что OPENID токен нормально передается из React frontend
- Проблема возникает именно тогда, когда резолверы пытаются определить идентификатор для валидации
- Сохранение директивы @aws_api_key приводит к полному сбою из-за null идентификатора
Вопрос
Как правильно настроить AWS AppSync для поддержки обоих методов авторизации - OPENID_CONNECT и API_KEY, не нарушая существующую функциональность, и почему идентификатор приходит как null при наличии обоих методов авторизации?
AWS AppSync не может корректно обрабатывать несколько методов авторизации одновременно в одном конвейере резолверов, поэтому вы сталкиваетесь с тем, что идентификатор приходит как null при наличии директив OPENID_CONNECT и API_KEY одновременно. Система авторизации разработана для оценки методов в определенном порядке, и при наличии конфликтующих директив оценка может завершиться ошибкой или вернуть null-идентификаторы. Чтобы поддержать оба метода авторизации, необходимо разделить их, создав разные резолверы или используя авторизацию на уровне API Gateway до того, как запросы достигнут AppSync.
Содержание
- Поведение авторизации AWS AppSync
- Почему идентификатор становится null при нескольких методах
- Правильная конфигурация для смешанной авторизации
- Альтернативные подходы
- Шаги по устранению неполадок
Поведение авторизации AWS AppSync
AWS AppSync оценивает методы авторизации в определенном порядке, когда в резолвере присутствуют несколько директив. Система авторизации обрабатывает эти директивы последовательно, и если любая директива завершается ошибкой или конфликтует с другими, это может привести к установке идентификатора в null.
Когда у вас есть директивы @aws_oidc и @aws_api_key на одном резолвере, AppSync пытается проверить запрос с использованием обоих методов одновременно. Это создает конфликт, потому что:
- OPENID_CONNECT ожидает проверку JWT-токена
- API_KEY ожидает ключ API в заголовках
- Система авторизации не может определить, какой метод должен иметь приоритет
Ключевое замечание: Авторизация в AppSync разработана для работы с одним основным методом авторизации на резолвер или API, а не с несколькими методами, оцениваемыми одновременно.
Почему идентификатор становится null при нескольких методах
Проблема с null-идентификатором возникает из-за того, как AppSync обрабатывает директивы авторизации:
- Порядок авторизации: AppSync оценивает методы авторизации в определенном порядке (обычно сначала API_KEY, затем другие методы)
- Конфликт проверки: Когда оба метода присутствуют, система может частично проверить один метод, но не завершить проверку для другого
- Вмешательство заголовков: Вставка заголовка
x-api-keyуказывает на то, что срабатывает авторизация API_KEY, потенциально переопределяя или конфликтуя с проверкой OIDC-токена - Контекст резолвера: Переменная
$identityстановится null, когда система авторизации не может успешно аутентифицировать запрос через какой-либо один метод
Важно: Согласно документации AWS, при настройке нескольких методов авторизации используется только первый успешно аутентифицированный метод, а конфликты могут приводить к сбоям аутентификации.
Правильная конфигурация для смешанной авторизации
Метод 1: Отдельные резолверы для разных типов авторизации
Наиболее надежный подход — создание отдельных резолверов для разных сценариев авторизации:
# Схема с отдельными типами авторизации
type Query {
# Для запросов с аутентификацией API_KEY
getPublicData: [String] @aws_api_key
# Для запросов с аутентификацией OPENID_CONNECT
getPrivateData: [String] @aws_oidc
}
type Mutation {
# Мутация с API_KEY
updatePublicData(id: ID!, data: String!): UpdateResult
@aws_api_key
# Мутация с OIDC
updatePrivateData(data: String!): UpdateResult
@aws_oidc
}
Метод 2: Использование API Gateway как слоя авторизации
Реализуйте авторизацию на уровне API Gateway до того, как запросы достигнут AppSync:
# Пример конфигурации API Gateway
Resources:
AppSyncAPI:
Type: AWS::AppSync::GraphQLApi
Properties:
AuthenticationType: API_KEY
Name: "AppSync with Gateway Auth"
ApiGateway:
Type: AWS::ApiGateway::RestApi
Properties:
Name: "Auth Gateway"
ApiGatewayStage:
Type: AWS::ApiGateway::Stage
Properties:
RestApiId: !Ref ApiGateway
StageName: "prod"
AccessLogSetting:
DestinationArn: !Ref LogGroup
Format: "$context.identity.sourceIp $context.identity.caller $context.identity.user [$context.requestTime] \"$context.httpMethod $context.resourcePath $context.protocol\" $context.status $context.responseLength $context.requestId"
MethodSettings:
- ResourcePath: "/*"
HttpMethod: "*"
DataTraceEnabled: true
LoggingLevel: INFO
MetricsEnabled: true
Метод 3: Условная авторизация в резолверах
Используйте логику резолвера для обработки разных типов авторизации:
// Шаблон резолвера VTL для смешанной авторизации
#if($context.identity.claims)
// Аутентификация OIDC - обработка утверждений JWT
{
"version": "2018-05-29",
"operation": "Invoke",
"payload": {
"userId": "$context.identity.claims.sub",
"email": "$context.identity.claims.email"
}
}
#elseif($context.identity.apiKey)
// Аутентификация по API ключу
{
"version": "2018-05-29",
"operation": "Invoke",
"payload": {
"apiKey": "$context.identity.apiKey",
"source": "api-key"
}
}
#else
// Нет действительной аутентификации
{
"version": "2018-05-29",
"operation": "Invoke",
"payload": {
"error": "Unauthorized - No valid authentication method"
}
}
#end
Альтернативные подходы
1. Использование нескольких API AppSync
Создайте отдельные API AppSync для разных требований авторизации:
Resources:
AppSyncPublicAPI:
Type: AWS::AppSync::GraphQLApi
Properties:
AuthenticationType: API_KEY
Name: "Public AppSync API"
AppSyncPrivateAPI:
Type: AWS::AppSync::GraphQLApi
Properties:
AuthenticationType: OIDC
Name: "Private AppSync API"
OpenIDConnectConfig:
AuthTTL: 900
ClientId: !GetAtt OIDCApp.ClientId
IatTTL: 3600
Issuer: "https://your-oidc-provider.com"
2. Авторизация Lambda@Edge
Реализуйте логику авторизации на краю CloudFront:
// Функция Lambda@Edge для авторизации
exports.handler = async (event) => {
const request = event.Records[0].cf.request;
// Проверка наличия OIDC-токена
const authHeader = request.headers['authorization'] ?
request.headers['authorization'][0].value : null;
if (authHeader && authHeader.startsWith('Bearer ')) {
// Обработка OIDC-токена
const token = authHeader.substring(7);
// Проверка токена и переадресация в AppSync с правильными заголовками
request.headers['x-amzn-oidc-data'] = [{ key: 'x-amzn-oidc-data', value: token }];
} else if (request.headers['x-api-key']) {
// Обработка API ключа
// Переадресация как есть в конечную точку AppSync с авторизацией API_KEY
} else {
return {
status: '401',
statusDescription: 'Unauthorized',
headers: {
'www-authenticate': [{
key: 'www-authenticate',
value: 'Bearer, ApiKey'
}]
}
};
}
return request;
};
Шаги по устранению неполадок
Шаг 1: Проверка конфигурации авторизации
- Проверьте конфигурацию вашего API AppSync в консоли AWS
- Убедитесь, что в качестве основного метода авторизации выбран только один метод
- Проверьте, что в резолверах нет конфликтующих директив авторизации
Шаг 2: Тестирование отдельных методов авторизации
Тестируйте каждый метод авторизации отдельно:
# Тест с API ключом
curl -H "x-api-key: YOUR_API_KEY" \
-X POST \
-H "Content-Type: application/json" \
-d '{"query": "query { getPublicData }"}' \
YOUR_APPSYNC_ENDPOINT
# Тест с OIDC-токеном
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-X POST \
-H "Content-Type: application/json" \
-d '{"query": "query { getPrivateData }"}' \
YOUR_APPSYNC_ENDPOINT
Шаг 3: Проверка журналов CloudTrail
Просмотрите журналы CloudTrail для событий аутентификации:
# Проверка событий аутентификации AppSync
aws logs filter-log-events \
--log-group-name /aws/appsync/apis/YOUR_API_ID \
--filter-pattern '{ $.eventType = "AUTHORIZE" }' \
--output table
Шаг 4: Использование отладки AppSync
Включите отладку AppSync в ваших резолверах для просмотра точного потока авторизации:
// Добавление отладки в шаблон резолвера
#set($context.stash.debug = "Authorization check: $context.identity")
#if($context.identity.apiKey)
#set($context.stash.authMethod = "API_KEY")
#elseif($context.identity.claims)
#set($context.stash.authMethod = "OIDC")
#end
{
"version": "2018-05-29",
"operation": "Invoke",
"payload": {
"debug": "$context.stash"
}
}
Источники
- Руководство разработчика AWS AppSync - Авторизация
- Ссылка на директивы схемы AWS AppSync
- Резолверы AWS AppSync - Работа с идентификатором
- Лучшие практики AWS AppSync - Аутентификация и авторизация
- Интеграция AWS API Gateway с AppSync
Заключение
Конфликты авторизации в AWS AppSync возникают потому, что сервис не предназначен для одновременной оценки нескольких методов авторизации в одном конвейере резолверов. Чтобы правильно поддержать как OPENID_CONNECT, так и API_KEY авторизацию, вы должны:
- Разделять методы авторизации, создавая отдельные резолверы или операции GraphQL для каждого типа аутентификации
- Использовать API Gateway как слой авторизации для обработки аутентификации до того, как запросы достигнут AppSync
- Реализовать условную логику в резолверах для обработки разных сценариев аутентификации
- Рассмотреть возможность использования нескольких API AppSync, если вам нужны полностью отдельные среды авторизации
Проблема с null-идентификатором возникает потому, что система авторизации AppSync не может успешно проверять запросы при наличии нескольких конфликтующих директив авторизации. Реализуя разделение ответственности и правильное分层ирование авторизации, вы можете поддерживать как функциональность API_KEY, так и OPENID_CONNECT без конфликтов.