Configuring authorization and authentication to secure Event APIs
AWS AppSync Events offers the following authorization types to secure Event APIs: API keys, Lambda, IAM, OpenID Connect, and Amazon Cognito user pools. Each option provides a different method of security.
-
API Key authorization: A simple key-based security option, with keys generated by the AppSync service.
-
Lambda authorization: Enables custom authorization logic, evaluated by an Lambda function .
-
IAM authorization: Utilizes AWS's signature version 4 signing process, allowing fine-grained access control through IAM policies.
-
OpenID Connect authorization: Integrates with OIDC-compliant services for user authentication.
-
Amazon Cognito user pools: Implements group-based access control using Amazon Cognitos user management features.
Authorization types
There are five ways you can authorize applications to interact with your AWS AppSync Event API. You specify which authorization type you use by specifying one of the following authorization type values in your AWS AppSync API or AWS CLI call:
-
-
API_KEY
-
For using API keys.
-
-
-
AWS_LAMBDA
-
For using an AWS Lambda function.
-
-
-
AWS_IAM
-
For using AWS Identity and Access Management permissions.
-
-
-
OPENID_CONNECT
-
For using your OpenID Connect provider.
-
-
-
AMAZON_COGNITO_USER_POOLS
-
For using an Amazon Cognito user pool.
-
When you define your API, you configure the authorization mode to connect to your Event API WebSocket. You also configure the default authorization modes to use when publishing and subscribing to messages. You can use different authorization modes for each configuration. For example, you might want your publisher to use IAM authorization for a backend process running on an Amazon EC2 instance, but you want your clients to use an API key to subscribe to messages.
Optionally, you can also configure the authorization mode to use for publishing and subscribing to messages on a namespace. When defined, these settings override the default configuration on your API. This enables you to have different settings for different namespaces on your API.
To learn more about using authorization types in your WebSocket operations, see Understanding the Event API WebSocket protocol
To learn more about publishing events using the HTTP endpoint, see Publish via HTTP.
API_KEY authorization
API Keys allow unauthenticated clients to securely use your API. An API key is a hard-coded value in your application that is generated by the AWS AppSync service. You can rotate API keys from the AWS Management Console, the AWS CLI, or from the AWS AppSync API Reference.
API keys are configurable for up to 365 days, and you can extend an existing expiration date for up to another 365 days from that day.
On the client, the API key is specified by the header x-api-key
.
For example, if your API_KEY
is ABC123
, you can publish a message to a channel using the HTTP endpoint via curl as follows:
curl --location "https://YOUR_EVENT_API_ENDPOINT/event" \ --header 'Content-Type: application/json' \ --header "x-api-key:ABC123" \ --data '{ "channel":"/news", "events":["\"Breaking news!\""] }'
AWS_LAMBDA authorization
You can implement your own API authorization logic using an AWS Lambda function. When you use Lambda functions for authorization, the following constraint applies.
-
A Lambda function authorizer must not return more than 5MB of contextual data.
For example, if your authorization token is 'ABC123'
, you can publish via curl
as follows:
curl --location "https://YOUR_EVENT_API_ENDPOINT/event" \ --header 'Content-Type: application/json' \ --header "Authorization:ABC123" \ --data '{ "channel":"/news", "events":["\"Breaking news!\""] }'
Lambda functions are called before connection, publish, and subscription attempts. The return
value can be cached based on the API ID and the authentication token. By default, caching is not
turned on, but this can be enabled at the API level or by setting the ttlOverride
value in a function's return value.
You can also specify a regular expression that validates authorization tokens before the function is called. These regular expressions are used to validate that an authorization token is of the correct format before your function is called. Any request using a token which does not match this regular expression will be denied automatically.
Lambda functions used for authorization require a principal policy for
appsync.amazonaws.com
to be applied on them to allow AWS AppSync to call them. This
action is done automatically in the AWS AppSync console; The AWS AppSync console does
not remove the policy. For more information on attaching policies to Lambda
functions, see Working with resource-based IAM policies in Lambda in the AWS Lambda Developer Guide.
The Lambda function you specify will receive an event with the following shape:
{ "authorizationToken": "ExampleAUTHtoken123123123", "requestContext": { "apiId": "aaaaaa123123123example123", "accountId": "111122223333", "requestId": "f4081827-1111-4444-5555-5cf4695f339f", "operation": "EVENT_CONNECT", "channelNamespaceName": "news", "channel": "/news/latest" }, "requestHeaders": { "header": "value" } }
The operation property indicates the operation that is being evaluated and can have the following values:
EVENT_CONNECT
EVENT_SUBSCRIBE
EVENT_PUBLISH
The event object contains the headers that were sent in the request from the application client to AWS AppSync.
The authorization function must return at least isAuthorized
, a boolean indicating whether the request is authorized to execute the operation on the Event API.
If this value is true, execution of the Event API continues. If this value is false, an UnauthorizedException
is raised.
Accepted keys
isAuthorized
(boolean, required)-
A boolean value indicating if the value in
authorizationToken
is authorized to execute the operation on the Event API.If this value is true, execution of the Event API continues. If this value is false, an
UnauthorizedException
is raised handlerContext
(JSON object, optional)-
A JSON object visible as
$ctx.identity.handlerContext
in your handlers. The object is a map of strings. For example, if the following structure is returned by a Lambda authorizer:{ "isAuthorized":true "handlerContext": { "banana":"very yellow", "apple":"very green" } }
The value of
ctx.identity.handlerContext.apple
in handlers will bevery green
. ThehandlerContext
object only supports key-value pairs. Nested keys are not supported.Warning
The total size of this JSON object must not exceed 5MB.
ttlOverride
(integer, optional)-
The number of seconds that the response should be cached for. If no value is returned, the value from the API is used. If this is 0, the response is not cached.
Lambda authorizers have a timeout of 10 seconds. We recommend designing functions to execute in the shortest amount of time possible to scale the performance of your API.
Multiple AWS AppSync APIs can share a single authentication Lambda function. Cross-account authorizer use is not supported.
The following example describes a Lambda function that demonstrates the various authentication and failure states that a Lambda function can have when used as an AWS AppSync authorization mechanism.
def handler(event, context): # This is the authorization token passed by the client token = event.get('authorizationToken') # If a lambda authorizer throws an exception, it will be treated as unauthorized. if 'Fail' in token: raise Exception('Purposefully thrown exception in Lambda Authorizer.') if 'Authorized' in token and 'ReturnContext' in token: return { 'isAuthorized': True, 'handlerContext': { 'key': 'value' } } # Authorized with no context if 'Authorized' in token: return { 'isAuthorized': True } # never cache response if 'NeverCache' in token: return { 'isAuthorized': True, 'ttlOverride': 0 } # not authorized if 'Unauthorized' in token: return { 'isAuthorized': False } # if nothing is returned, then the authorization fails. return {}
AWS_IAM authorization
This authorization type enforces the AWS signature version 4 signing process on your API. You can associate AWS Identity and Access Management (IAM) access policies with this authorization type. Your application can leverage this association by using an access key (which consists of an access key ID and secret access key) or by using short-lived, temporary credentials provided by Amazon Cognito Federated Identities.
The following is an example of an IAM role that has permission to perform all data operations.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "appsync:EventConnect", "appsync:EventPublish", "appsync:EventSubscribe", ], "Resource": [ "arn:aws:appsync:us-west-2:123456789012:apis/APIID/*" ] } ] }
OPENID_CONNECT authorization
This authorization type enforces OpenID
connect
An Issuer URL is the only required configuration value that you provide to AWS AppSync (for example,
https://auth.example.com
). This URL must be addressable over HTTPS. AWS AppSync appends
/.well-known/openid-configuration
to the issuer URL and locates the OpenID configuration at
https://auth.example.com/.well-known/openid-configuration
per the OpenID Connect Discoveryjwks_uri
key, which points
to the JSON Web Key Set (JWKS) document with the signing keys. AWS AppSync requires the JWKS to contain JSON
fields of kty
and kid
.
AWS AppSync supports a wide range of signing algorithms.
Signing algorithms |
---|
RS256 |
RS384 |
RS512 |
PS256 |
PS384 |
PS512 |
HS256 |
HS384 |
HS512 |
ES256 |
ES384 |
ES512 |
We recommend that you use the RSA algorithms. Tokens issued by the provider must include the time at which
the token was issued (iat
) and may include the time at which it was authenticated
(auth_time
). You can provide TTL values for issued time (iatTTL
) and
authentication time (authTTL
) in your OpenID Connect configuration for additional validation. If
your provider authorizes multiple applications, you can also provide a regular expression
(clientId
) that is used to authorize by client ID. When the clientId
is present in
your OpenID Connect configuration, AWS AppSync validates the claim by requiring the clientId
to
match with either the aud
or azp
claim in the token.
To validate multiple client IDs use the pipeline operator (β|β) which is an βorβ in regular expression. For example, if your OIDC application has four clients with client IDs such as 0A1S2D, 1F4G9H, 1J6L4B, 6GS5MG, to validate only the first three client IDs, you would place 1F4G9H|1J6L4B|6GS5MG in the client ID field.
AMAZON_COGNITO_USER_POOLS authorization
This authorization type enforces OIDC tokens provided by Amazon Cognito user pools. Your application can leverage the users and groups in your handlers to apply custom business rules.
When using Amazon Cognito user pools, you can create groups that users belong to. This information is encoded in a JWT token that your application sends to AWS AppSync in an authorization header with each request.
curl --location "https://YOUR_EVENT_API_ENDPOINT/event" \ --header 'Content-Type: application/json' \ --header "Authorization:JWT_TOKEN" \ --data '{ "channel":"/news", "events":["\"Breaking news!\""] }'
Circumventing SigV4 and OIDC token authorization limitations
The following methods can be used to circumvent the issue of not being able to use your SigV4 signature or OIDC token as your Lambda authorization token when certain authorization modes are enabled.
If you want to use the SigV4 signature as the Lambda authorization token when the
AWS_IAM
and AWS_LAMBDA
authorization modes are enabled for AWS AppSync's
API, do the following:
To create a new Lambda authorization token, add random suffixes and/or prefixes to the SigV4 signature.
To retrieve the original SigV4 signature, update your Lambda function by removing the random prefixes and/or suffixes from the Lambda authorization token. Then, use the original SigV4 signature for authentication.
If you want to use the OIDC token as the Lambda authorization token when the OPENID_CONNECT
authorization mode or the AMAZON_COGNITO_USER_POOLS
and AWS_LAMBDA
authorization modes are enabled for AWS AppSync's API, do the following:
To create a new Lambda authorization token, add random suffixes and/or prefixes to the OIDC token. The Lambda authorization token should not contain a Bearer scheme prefix.
To retrieve the original OIDC token, update your Lambda function by removing the random prefixes and/or suffixes from the Lambda authorization token. Then, use the original OIDC token for authentication.