typescript - Anpassad auktorisator anropas inte för websocket connect-händelse


Jag försöker implementera en anpassad auktoriserare för en API Gateway Websocket API.

Jag har min anpassade auktoriserare deklarerad så här med CDK:

const authFunc = new lambda.Function(scope, utils.prefixed("WebsocketAuth"), {
    runtime: lambda.Runtime.NODEJS_18_X,
    handler: `auth.handler`,
    code: lambda.Code.fromAsset(lambdaPath),
    environment: {
        API_KEY_ID: apiKey.keyId
    }
});

const authorizer = new WebSocketLambdaAuthorizer(
    "WebsocketAuth",
    authFunc
);

const webSocketApi = new apigatewayv2.WebSocketApi(scope, 'WebSocketApi', {
    connectRouteOptions: {
        authorizer,
        integration: new integrations.WebSocketLambdaIntegration('ConnectHandler', connectFunc),
    },
    disconnectRouteOptions: {
        integration: new integrations.WebSocketLambdaIntegration('DisconnectHandler', disconnectFunc)
    },
    defaultRouteOptions: {
      integration: new integrations.WebSocketLambdaIntegration('DefaultHandler', defaultFunc),
    },
    routeSelectionExpression: '$request.body.action',
});

När jag försöker ansluta till detta Websocket API får jag en callback för stängd anslutning med kod 1006. Men när jag kollar Cloudwatch-loggarna finns det ingen logggrupp för min anpassade auktoriserare, så det verkar som om lambda-funktionen inte anropas som förväntat.

Jag ansluter så här:

ws = new WebSocket(`wss://${host}/${stage}?token=${authToken}`);

Innan den anpassade auktoriseraren lades till lyckades websocket-anslutningen, och API:et fungerade som förväntat.

Jag kan köra den anpassade auktoriseraren lambda med Test-funktionen i konsolen, och loggar skapas som förväntat.

Här är implementeringen av auktoriseringshanteraren:

import { APIGatewayRequestAuthorizerEvent, APIGatewayAuthorizerResult } from 'aws-lambda';

const secret = process.env.API_SECRET ?? '';

export const handler = async (event: APIGatewayRequestAuthorizerEvent): Promise<APIGatewayAuthorizerResult> => {

    console.log(`Event: ${JSON.stringify(event)}`);

    const query = event.queryStringParameters ?? { token: 'NONE' };
    const token = query['token'];

    console.log(`Query: ${JSON.stringify(query)}`);

    if (token === secret) {
        console.log(`Allowed`);
        return generatePolicy('user', 'Allow', event.methodArn);
    } else {
        console.log(`Denied`);
        return generatePolicy('user', 'Deny', event.methodArn);
    }

};

function generatePolicy(principalId: string, effect: string, resource: string) {
    return {
        principalId,
        policyDocument: {
        Version: '2012-10-17',
        Statement: [
            {
                Action: 'execute-api:Invoke',
                Effect: effect,
                Resource: resource,
            },
        ],
        },
    };
}

Vad saknar jag för att få den här anpassade auktoriseraren att fungera?

Svar #1

Jag klurade ut det. Jag var tvungen att lägga till argumentet identitySource i WebSocketLambdaAuthorizer-deklarationen:

const authorizer = new WebSocketLambdaAuthorizer(
    "WebsocketAuth",
    authFunc,
    {
        identitySource: ['route.request.querystring.token']
    }
);

Detta är nödvändigt, eftersom godkännaren tydligen inte kommer att anropas om fälten i identitySource inte är närvarande, och standard identitySource är Authorization-huvudet, vilket inte enkelt kan ställas in för websocket-anslutningar.