1

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.

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
Nick Wright
  • 87
  • 1
  • 9

1 Answers1

1

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='
Vlad Holubiev
  • 4,876
  • 7
  • 44
  • 59
  • Thanks, Vlad! I knew it was something along those lines, but you've saved me several hours or research and playing there! – Nick Wright Oct 14 '22 at 08:32
  • This solution does not work for me, the Lambda just times out. According to AWS Lambda docs, the user of http basic auth is not supported owing to the fact that it relies upon a http session, which is not possible in a stateless execution environment. – Adam893 Feb 28 '23 at 15:32