Http Endpoint - preflight OPTIONS not allowing Authorization Header

What I’m trying to do:

Provide an endpoint to authenticate Users against the Anvil Users file.

What I’ve tried and what’s not working:
I am using a Get with http Basic Authentication Authorization header.

My calling app is doing a preflight Options call (although Curl does not appear to use a preflight Options call so does not cause the error)

I keep getting Cors Errors even though Enable_Cors=True is set.
I originally had authenticate_users=True but I guessed that was stopping the Options call.

I have read everything in the Anvil.Works forum and tried to adapt the answers to my endpoint.

I have narrowed it down to Access-Control-Allow-Headers being the culprit but I can’t get anything other then Content-Type header allowed.

Code Sample:

@anvil.server.http_endpoint('/auth_user/',methods=["GET", "OPTIONS"],enable_cors=True)
def auth_user():
  print(anvil.server.request.method)
  if anvil.server.request.method == 'OPTIONS':
    r = anvil.server.HttpResponse()
    r.headers['Access-Control-Allow-Origin'] = '*'
    r.headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
    r.headers['Access-Control-Request-Method'] = '*'
    r.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'

    print(r.headers)
    return r
  else:
    # check User:Password from Authorization header against Anvil Users File

Errors: shown in Chrome tools

Access to fetch at 'https://myapp.anvil.app/_/api/auth_user/' from origin 'https://mycallingapp.com' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.

Curl Options Output:

C:\Users\user>curl -X OPTIONS https://myapp.anvil.app/_/api/auth_user/ -i
HTTP/1.1 200 OK
content-type: text/plain; charset=utf-8
access-control-allow-methods: POST, PUT, DELETE, GET, OPTIONS
access-control-request-method: *
access-control-allow-origin: *
access-control-allow-headers: content-type
content-length: 0
server: anvil
date: Tue, 03 May 2022 13:42:57 GMT
x-server: platform-server-blue-4

I have tried changing the access-control-allow-headers but curl always shows only content-type allowed.

It looks like access-control-allow-headers might even be hard coded in Anvil for Options calls!!

Any ideas of what I can try next?

It appears that enable_cors=True hard codes

Access-Control-Allow-Headers = Content-Type only!

You cannot override this (for example) with:

anvil.server.HttpResponse().headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'.

to allow additional headers.

So preflight OPTIONS calls from a Get (and I assume Post etc) with Basic Auth will fail as the Authorization Header is not allowed.

The solution (for me at least) was to remove the enable_cors=True from the endpoint decorator and set the CORS headers manually.

Here is my final (proof of concept) endpoint:

@anvil.server.http_endpoint('/auth_user/',methods=["GET", "OPTIONS"])
def auth_user():
  print(anvil.server.request.method)
  if anvil.server.request.method == 'OPTIONS':
    r = anvil.server.HttpResponse()
    r.headers['Access-Control-Allow-Origin'] = '*'
    r.headers['Access-Control-Allow-Methods'] = 'GET, OPTIONS'
    r.headers['Access-Control-Request-Method'] = '*'
    r.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
    print(r.headers)
    return r
  else:
    print("Username", anvil.server.request.username)
    print("Password", anvil.server.request.password)
    user = app_tables.users.get(email=anvil.server.request.username)
    if user is not None and bcrypt.checkpw(anvil.server.request.password.encode('utf-8'), user['password_hash'].encode('utf-8')):
      cu_tm_ref = user['tm_ref']
      cu_email = user['email']
    else:
      cu_tm_ref = ''
      cu_email = 'Login Failed'
    result = {'tm_ref': cu_tm_ref, 'email': cu_email}
    r = anvil.server.HttpResponse(200, result)
    r.headers['Access-Control-Allow-Origin'] = '*'
    r.headers['Access-Control-Allow-Methods'] = 'GET, OPTIONS'
    r.headers['Access-Control-Request-Method'] = '*'
    r.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
    print(anvil.server.HttpResponse())
    return r

This is all new to me so I may be trying to fix something that I should have done differently to begin with - but it works!