matthiask / django-authlib

Utilities for passwordless authentication (using magic links, Google, Facebook and Twitter OAuth currently)
https://django-authlib.readthedocs.io/
MIT License
61 stars 11 forks source link

Bug: Can't log in the Django Admin site - Error while fetching user data. Please try again. #10

Closed martarho closed 4 months ago

martarho commented 2 years ago

I've set up django-authlib for django-admin as per the documentation, but unfortunately I keep getting the error "Error while fetching user data. Please try again" when logging in.

ssologing

image

I am the admin of the GCP project where the Oauth2 client is set up and it all works with my front end application.

Any ideas on what could be going on here?

Some small details, in case they impact this problem:

My configuration

settings.py

INSTALLED_APPS = [
    "authlib.admin_oauth",  # keep before django.contrib.admin
   ...
]
...
# Django Admin SSO
GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_SSO_CLIENT")
GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_SSO_SECRET")

# patterns for .*@my-domain.com 
ADMIN_OAUTH_PATTERNS = [
    (r"^.*@my\-domain\.com$", lambda match: match[0]),
    (r"^.*@my\-domain\.com$", "marta@my-domain.com"),
]
...

urls.py

...
urlpatterns = [
    url(r"", include("authlib.admin_oauth.urls")),
    path("admin/", admin.site.urls),
    ...
    ]

Oauth2 set up oauth2-setup

Console output (anonymised, of course)

[23/May/2022 14:59:19] "GET /admin/__oauth__/?next= HTTP/1.1" 302 0
app_1  | [23/May/2022 14:59:21] "GET /admin/__oauth__/?state=XXXXXXXXXXXXX&code=VVVVVVVVVVVVVVVVVVVVVVVVVVVV-VS-AAAAA-CCCCCCCCCCCCCCCCCCCCCCC_CA&scope=email%20profile%20openid%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile&authuser=0&hd=my-domain.com&prompt=consent HTTP/1.1" 302 0
app_1  | [23/May/2022 14:59:21] "GET /admin/login/ HTTP/1.1" 200 2794
matthiask commented 2 years ago

Thanks for the excellent bug report!

Could you replace this line https://github.com/matthiask/django-authlib/blob/b5e4d6291602b43129cf38a4b1ea05a99c7641f7/authlib/google.py#L60 by something like this?

(You can apply temporary edits directly inside your virtualenv folder, e.g, venv/lib/python3.10/authlib/google.py or you could use a Git checkout, but the former is simpler most of the time and works just as good.)

        print(token)
        print(b64decode(token["id_token"].split(".")[1]))
        data = json.loads(b64decode(token["id_token"].split(".")[1]).decode("utf-8"))

The data should be a dictionary containing some information such as the email address and maybe your name etc.

If that fails too could you at least check what exception you're getting here?

https://github.com/matthiask/django-authlib/blob/b5e4d6291602b43129cf38a4b1ea05a99c7641f7/authlib/admin_oauth/views.py#L29

Thanks in advance!

matthiask commented 2 years ago

This is what I'm seeing when I'm printing the token btw:

{'access_token': '...',
 'expires_in': 3599,
 'scope': ['https://www.googleapis.com/auth/userinfo.profile',
           'openid',
           'https://www.googleapis.com/auth/userinfo.email'],
 'token_type': 'Bearer',
 'id_token': 'eyJhbGci____.eyJpc3MiO____.c9vlh-lF4qyaDz_____',
 'expires_at': 1653326834.23049}

I'm wondering if the id_token entry is missing or is not formatted as a JWT; the data section of the JWT should contain the verified email address, but it seems that for some reason the token you're getting is formatted differently.

martarho commented 2 years ago

Hi @matthiask!

It seems the error is already at line 50: https://github.com/matthiask/django-authlib/blob/b5e4d6291602b43129cf38a4b1ea05a99c7641f7/authlib/google.py#L50

I tried debugging the exception and this is what I got:

Exception type InsecureTransportError Arguments:
('(insecure_transport) OAuth 2 MUST utilize https.',)

I'm trying to run my app over https with a self-signed certificate to see if it works. I'll be back once I succeed! (or fail)

It was a fail, but because of the development mode not allowing me to run it over HTTPS. Which in a way is expected. Not sure how to proceed from here though, so any ideas will be definitely welcome!

matthiask commented 2 years ago

Oh, that's right. You could add the following lines e.g. to your settings.py:

if DEBUG:
    os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

(See https://github.com/oauthlib/oauthlib/blob/b69fa53fd836dc559aa7fcd78ce075bcbe361629/docs/oauth2/security.rst#environment-variables)

martarho commented 2 years ago

Hi @matthiask, thanks! I can confirm this solved the problem :)

matthiask commented 2 years ago

@martarho Good to hear! I already added a note to the documentation. I hope this helps the next person struggling with the same problem. Thanks!

matthiask commented 4 months ago

Fixed in a6959d94