Http authentication via users service

Hello,

I have been learning about how to create http endpoints inside anvil and I ran into an issue with the basic authentication using users service.

Here is a link to the docs:

I set up the endpoint just like the example shows, however when I send the email and password through postman I get an Unathorized error. I also tried to send it with curl like the example shows, but I get the same error.

The only way it works is if I open the endpoint in a browser, where an authentication window pops up and requests the email and password.

My server side code:

@anvil.server.http_endpoint("/protected1", authenticate_users=True)
def serve_protected_content():
  return {"authentication":"successful","users_email":request.user['email']}

Url:
https://[MY_CUSTOM_DOMAIN]/_/api/protected1

Curl command:

curl -u [USER_EMAIL]:[USERS_PASSWORD] https://[MY_CUSTOM_DOMAIN]/_/api/protected1

Result : Unauthorized

Browser link:
https://[MY_CUSTOM_DOMAIN]/_/api/protected1
Result: {“authentication”:“successful”,“users_email”:[THE_GIVEN_EMAIL]}

Postman:
Basic Authentication with email and password and the postman’s standard headers (Postman-token, content-length,…)
Body: None
Params: None
Result: Unathorized

I also tried changing the endpoint to

@http_endpoint("/protected", require_credentials=True)

This way I recieve the sent email and password, but I have to authenticate the users myself. At the moment I do not need more complicated authentications with tokens, so I would settle with the first one, if it worked.

I also found another topic regarding this from April, unfortunately it was ignored.
The topic’s link:

Am I missing something or misunderstood the documentation, that this should work?
Can somebody help with this?

Thanks in advance,
Arpad

Update:

Since I could not find an answer, I wrote a separate app, which would handle the authentication for the users and ran into an issue with the multiple factor authentication. As I found out, if you enable the 2 step verification, then you can not authenticate the users via api request, since you can not handle the mfa key part of the authentication ( or I do not know about it ).

Is there a way to authenticate users without 2 step verification, if it is enabled? Or is there a better way to solve this?

Thanks in advance,
Arpad

After a couple of hours of docs reading I found a very handful function: anvil.users.force.login(user).
This bypasses the 2 step verification system and logs the given user in. All I have to do before this is to authenticate the user manually by

def login_with_password(username, password):
  user = app_tables.users.get(username=username)
  if user is not None and bcrypt.checkpw(password.encode('utf-8'), user['password_hash'].encode('utf-8')):
    anvil.users.force.login(user)
    return user

Here is also the http endpoint:

@anvil.server.http_endpoint("/auth",require_credentials=True)
def auth():
  user = login_with_password(username=request.username,password=request.password)
  if user is not None:
    return anvil.server.HttpResponse(200, "Login was succesfull")
  return anvil.server.HttpResponse(401, "Unauthorized")

Hopefully, if someone encounters this problem, this thread may spare a couple of hours of their time.

3 Likes

Thank you very much, very helpful.
Based on this I have suggested a doc modification: Anvil Documentation Suggestions [ON-GOING] - #101 by mjmare