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.

1
  • As an aside, please be careful with the tags you use. the [lambda] tag is not for the aws service Commented Oct 13, 2022 at 16:58

1 Answer 1

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='
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, Vlad! I knew it was something along those lines, but you've saved me several hours or research and playing there!
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.