Working AWS Websocket JWT Authorizer

I was trying to add JWT authentication to an AWS web socket endpoint and it wasn’t working. My problem was simple and it was even spelled out mentioned in passing somewhere in the AWS docs and it still took me a long time to figure it out. The answer is that only request style authenticators are supported, not token. The docs say that here in that it doesn’t mention a token authorizer and explicitly states that only request is supported here. This post also makes the same point.

In Serverless the configuration for the authorizer looks like this:

    handler: bin/websocket_authorizer
        - ./bin/websocket_authorizer

    handler: bin/connection_handler
      - websocket:
          route: $connect
            name: websocketAuthorizer
            identitySource: 'route.request.header.Authorization'
        - ./bin/connection_handler

Then a Golang version of the authorizer would look something like this:

package main

import (


// note the APIGatewayCustomAuthorizerRequestTypeRequest that must 
// be the type of the request parameter for Websocket authorizers
func handler(ctx context.Context, request events.APIGatewayCustomAuthorizerRequestTypeRequest) (events.APIGatewayCustomAuthorizerResponse, error) {
  token := request.Headers["Authorization"]
  tokenSlice := strings.Split(token, " ")
  var bearerToken string
  if len(tokenSlice) > 1 {
    bearerToken = tokenSlice[len(tokenSlice)-1]
  } else {
    return events.APIGatewayCustomAuthorizerResponse{}, 

  err := authorizeToken( bearerToken )
  if nil != err {
    return events.APIGatewayCustomAuthorizerResponse{}, errors.New("Unauthorized")

  return generatePolicy(), nil

func generatePolicy() events.APIGatewayCustomAuthorizerResponse {
	authResponse := events.APIGatewayCustomAuthorizerResponse{PrincipalID: "principal"}

		authResponse.PolicyDocument = events.APIGatewayCustomAuthorizerPolicy{
      Version: "2012-10-17",
      Statement: []events.IAMPolicyStatement{
          Action:   []string{"execute-api:Invoke"},
          Effect:   "allow",
          Resource: []string{"*"},
  return authResponse

func authorizeToken( token string ) error {
  // do something to authorizer the token here
  return nil

func main() {

Note that the Serverless declaration doesn’t have a type parameter, unlike for REST APIs, that’s the first hint. In the Go code the parameter type is the excellently named APIGatewayCustomAuthorizerRequestTypeRequest. If instead you try to use an APIGatewayCustomAuthorizerRequest it will be invoked properly but the AuthorizationToken property will not be populated with your token. That’s why I’m retrieving the token explicitly from request.Headers["Authorization"]. One of the things that confused me was the IdentitySource in the configuration for the authorizer that can be used to reference the header, but it is either ignored or used just for pre-validation of the request.

Leave a Reply