I am deploying a serverless app on AWS and have some issues while trying to access my serverless application from the frontend. I have an impression that the issue is with the backend and more specifically with the serverless.yml configuration file (See first lines of codes below) or rather with my auth0Authorizer.ts file (see second lines of codes below). When I log into my frontend app, I receive a 403 error message that says User is not authorized to access this resource with an explicit deny
. I really doubt if this related any on configuration on AWS.
org: name
app: serverless-todo-app-app
service:
name: serverless-todo-app
package:
individually: true
plugins:
- serverless-webpack
- serverless-iam-roles-per-function
- serverless-reqvalidator-plugin
- serverless-aws-documentation
provider:
name: aws
runtime: nodejs8.10
stage: ${opt:stage, 'dev'}
region: ${opt:region, 'us-west-1'}
tracing: true
environment:
TODOS_TABLE: Todos-v4-${self:provider.stage}
USER_ID_INDEX: UserIdIndex
SIGNED_URL_EXPIRATION: 300
IMAGES_S3_BUCKET: 'severless-todo-app-bucket-v1-${self:provider.stage}'
DYNAMODB_TABLE: TableName
TableName: ${self:provider.environment.TODOS_TABLE}
AUTH_0_SECRET: ***********************************
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:Scan
- dynamodb:PutItem
- dynamodb:GetItem
- codedeploy:*
- xray:PutTelemetryRecords
- xray:PutTraceSegments
Resource:
- '*'
- Effect: Allow
Action:
- s3:GetObject
- xray:PutTelemetryRecords
- xray:PutTraceSegments
Resource: arn:aws:s3:::${self:provider.environment.IMAGES_S3_BUCKET}/*
custom:
documentation:
api:
info:
version: v1.0.0
title: Udagram API
description: Serverless application
models:
- name: TodoRequest
contentType: application/json
schema: ${file(models/create-todo-request.json)}
functions:
Auth:
handler: src/lambda/auth/auth0Authorizer.handler
# TODO: Configure this function
GetTodos:
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:GetItem
Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.TODOS_TABLE}
handler: src/lambda/http/getTodos.handler
events:
- http:
authorizer: Auth
method: get
path: todos
cors: true
# TODO: Configure this function
CreateTodo:
handler: src/lambda/http/createTodo.handler
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:PutItem
- xray:PutTelemetryRecords
- xray:PutTraceSegments
Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.TODOS_TABLE}
events:
- http:
authorizer: Auth
method: post
path: todos
cors: true
reqValidatorName: RequestBodyValidator
documentation:
summary: Create a new todo
description: Create a new todo
requestModels:
'application/json': TodoRequest
# TODO: Configure this function
UpdateTodo:
handler: src/lambda/http/updateTodo.handler
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:UpdateItem
- xray:PutTelemetryRecords
- xray:PutTraceSegments
Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.TODOS_TABLE}
events:
- http:
authorizer: Auth
method: patch
path: todos/{todoId}
cors: true
# TODO: Configure this function
DeleteTodo:
handler: src/lambda/http/deleteTodo.handler
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:DeleteItem
Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.TODOS_TABLE}
events:
- http:
authorizer: Auth
method: delete
path: todos/{todoId}
cors: true
# TODO: Configure this function
GenerateUploadUrl:
handler: src/lambda/http/generateUploadUrl.handler
iamRoleStatements:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
- xray:PutTelemetryRecords
- xray:PutTraceSegments
Resource: arn:aws:s3:::${self:provider.environment.IMAGES_S3_BUCKET}/*
- Effect: Allow
Action:
- dynamodb:PutItem
- dynamodb:GetItem
- dynamodb:UpdateItem
Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.TODOS_TABLE}
events:
- http:
authorizer: Auth
method: post
path: todos/{todoId}/attachment
cors: true
resources:
Resources:
# TODO: Add any necessary AWS resources
AttachmentsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:provider.environment.IMAGES_S3_BUCKET}
CorsConfiguration:
CorsRules:
-
AllowedOrigins:
- '*'
AllowedHeaders:
- '*'
AllowedMethods:
- GET
- PUT
- POST
- DELETE
- HEAD
MaxAge: 0
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
PolicyDocument:
Id: MyPolicy
Version: "2012-10-17"
Statement:
- Sid: PublicReadForGetBucketObjects
Effect: Allow
Principal: '*'
Action: 's3:GetObject'
Resource: 'arn:aws:s3:::${self:provider.environment.IMAGES_S3_BUCKET}/*'
Bucket: !Ref AttachmentsBucket
GatewayResponseDefault4XX:
Type: AWS::ApiGateway::GatewayResponse
Properties:
ResponseParameters:
gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
gatewayresponse.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
gatewayresponse.header.Access-Control-Allow-Methods: "'GET,OPTIONS,POST'"
ResponseType: DEFAULT_4XX
RestApiId:
Ref: ApiGatewayRestApi
RequestBodyValidator:
Type: AWS::ApiGateway::RequestValidator
Properties:
Name: 'request-body-validator'
RestApiId:
Ref: ApiGatewayRestApi
ValidateRequestBody: true
ValidateRequestParameters: false
TodosDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: todoId
AttributeType: S
- AttributeName: userId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: todoId
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
TableName: ${self:provider.environment.TODOS_TABLE}
GlobalSecondaryIndexes:
- IndexName: ${self:provider.environment.USER_ID_INDEX}
KeySchema:
- AttributeName: userId
KeyType: HASH
Projection:
ProjectionType: ALL
import { CustomAuthorizerEvent, CustomAuthorizerResult, CustomAuthorizerHandler } from 'aws-lambda'
import 'source-map-support/register'
import { verify } from 'jsonwebtoken'
import { JwtToken } from '../../auth/JwtToken'
const auth0Secret = process.env.AUTH_0_SECRET
export const handler: CustomAuthorizerHandler = async (event: CustomAuthorizerEvent): Promise<CustomAuthorizerResult> => {
try {
const decodedToken = verifyToken(event.authorizationToken)
console.log('User was authorized')
return {
principalId: decodedToken.sub,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Action: 'execute-api:Invoke',
Effect: 'Allow',
Resource: '*'
}
]
}
}
} catch (e) {
console.log('User was not authorized', e.message)
return {
principalId: 'user',
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Action: 'execute-api:Invoke',
Effect: 'Deny',
Resource: '*'
}
]
}
}
}
}
function verifyToken(authHeader: string): JwtToken {
if (!authHeader)
throw new Error('No authentication header')
if (!authHeader.toLowerCase().startsWith('bearer '))
throw new Error('Invalid authentication header')
const split = authHeader.split(' ')
const token = split[1]
return verify(token, auth0Secret) as JwtToken
}
When AWS says explicit Deny that means somewhere in the chain of IAM policies, there was a Deny for that action. In this case the only policy is the session policy that your authorizer Lambda provides. As @hephalump mentioned in the comments and according to your code it happens when there was an error, so check the logs to see what needs to be done.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.