Nick Wright
Nick Wright

Reputation: 111

Basic Auth is failing in AWS Lambda function

I'm calling a REST API with basic authentication in an AWS Lambda function. This is my code

import json, os, base64
from urllib import request

def lambda_handler(event, context):

retStatusCode = 0
retBody = ""

try:
    
    url = os.environ['URL']
    username = os.environ['USERNAME']
    password = os.environ['PASSWORD']

    requestURL = url + "/" + event['queueID'] + "/" + event['cli'];

    #print ("QUEUEID IS: " + event['queueID'])
    #print ("CLI IS: " + event['cli'])
    #print ("URL IS: " + requestURL)

    req = request.Request(requestURL, method="POST")
    myStr = '%s:%s' % (username, password)

    myBytes = myStr.encode("utf-8")

    base64string = base64.b64encode(myBytes)

    req.add_header("Authorization", "Basic %s" % base64string)
    resp = request.urlopen(req)

    responseJSON = json.load(resp)
    
    retStatusCode = responseJSON["Result"]
    retBody = responseJSON["Message"]
    
except Exception as e:
    
    retStatusCode = 500
    retBody = "An exception occurred: " + str(e)

return {
    'statusCode': retStatusCode,
    'body': retBody
}

However, I'm getting a "HTTP Error 401: Unauthorized" returned. If I call the API method in Postman with the same credentials, it returns data successfully, so I figure it must be something to do with the format of the header I'm adding, but just can't see what's wrong.

Upvotes: 1

Views: 1213

Answers (1)

Vlad Holubiev
Vlad Holubiev

Reputation: 5154

The problem is in this line:

req.add_header("Authorization", "Basic %s" % base64string)

From the documentation, base64.b64encode method is designed to "return the encoded bytes".

If you try to execute this code in REPL, you'll see that your resulting header looks wrong. It concatenates string with bytes:

>>> "Basic %s" % base64string
"Basic b'aGVsbG86d29ybGQ='"

You can read more about Python's b' syntax here.

So you need to decode the string back to utf8.

req.add_header("Authorization", "Basic %s" % base64string.decode('utf-8'))

The result will look a like a valid Auth header now:

>>> "Basic %s" % base64string.decode('utf-8')
'Basic aGVsbG86d29ybGQ='

Upvotes: 1

Related Questions