Open vinodhkumartandrothu opened 1 month ago
I have tried setting up the Django Microsoft SSO integration using both Poetry (please see above log) and a standard Python virtual environment. Despite following the necessary configuration steps in both environments, I am encountering the same issue: after successful authentication, the system redirects back to the admin login page instead of granting access. The following logs are from my current Python virtual environment setup, and the issue persists just as it did when using Poetry. (Added additional loggers.)
Log:
Converted retries value: 1 -> Retry(total=1, connect=None, read=None, redirect=None, status=None)
Initializing with Entra authority: https://login.microsoftonline.com/74xx
Starting new HTTPS connection (1): login.microsoftonline.com:443
https://login.microsoftonline.com:443 "GET /7xx7/v2.0/.well-known/openid-configuration HTTP/1.1" 200 1753
openid_config("https://login.microsoftonline.com/7xxx7/v2.0/.well-known/openid-configuration") = {'token_endpoint': 'https://login.microsoftonline.com/dre/oauh2/v2.0/', 'token_endpoint_auth_methods_supported': ['client_secret_post', 'private_key_jwt', 'client_secret_basic'], 'jwks_uri': 'https://login.microsoftonline.com/76556/discovery/v2.0/keys', 'response_modes_supported': ['query', 'fragment', 'form_post'], 'subject_types_supported': ['pairwise'], 'id_token_signing_alg_values_supported': ['RS256'], 'response_types_supported': ['code', 'id_token', 'code id_token', 'id_token token'], 'scopes_supported': ['openid', 'profile', 'email', 'offline_access'], 'issuer': 'https://login.microsoftonline.com/rtb7/v2.0', 'request_uri_parameter_supported': False, 'userinfo_endpoint': 'https://graph.microsoft.com/oidc/userinfo', 'authorization_endpoint': 'https://login.microsoftonline.com/tyuyu7/oauth2/v2.0/authorize', 'device_authorization_endpoint': 'https://login.microsoftonline.com/ttyutyu/oauth2/v2.0/devicecode', 'http_logout_supported': True, 'frontchannel_logout_supported': True, 'end_session_endpoint': 'https://login.microsoftonline.com/tyuf1b7/oauth2/v2.0/logout', 'claims_supported': ['sub', 'iss', 'cloud_instance_name', 'cloud_instance_host_name', 'cloud_graph_host_name', 'msgraph_host', 'aud', 'exp', 'iat', 'auth_time', 'acr', 'nonce', 'preferred_username', 'name', 'tid', 'ver', 'at_hash', 'c_hash', 'email'], 'kerberos_endpoint': 'https://login.microsoftonline.com/7xxxx/kerberos', 'tenant_region_scope': 'NA', 'cloud_instance_name': 'microsoftonline.com', 'cloud_graph_host_name': 'graph.windows.net', 'msgraph_host': 'graph.microsoft.com', rl': 'https://pas.windows.net'}
Broker enabled? None
2024-09-17 10:27:52.266 | DEBUG | django_microsoft_sso.main:get_netloc:40 - Find Netloc using MICROSOFT_SSO_CALLBACK_DOMAIN
2024-09-17 10:27:52.266 | DEBUG | django_microsoft_sso.main:get_redirect_uri:55 - Callback URI: http://localhost:8000/microsoft_sso/callback/
Page /microsoft_sso/login/ took 0.6013 seconds to load.
"GET /microsoft_sso/login/?next=null HTTP/1.1" 302 0
"GET /microsoft_sso/login/?next=null HTTP/1.1" 302 0
Converted retries value: 1 -> Retry(total=1, connect=None, read=None, redirect=None, status=None)
Initializing with Entra authority: https://login.microsoftonline.comxxxx
Starting new HTTPS connection (1): login.microsoftonline.com:443
'https://login.microsoftonline.comxxx7/oauth2/v2.0/authorize', 'device_authorization_endpoint': 'https://login.microsoftonline.com/7448cd93-a4af-42bc-a76b-890ed150f1b7/oauth2/v2.0/devicecode', 'http_logout_supported': True, 'frontchannel_logout_supported': True, 'end_session_endpoint': 'https://login.microsoftonline.com/thj0f1b7/oauth2/v2.0/logout', 'claims_supported': ['sub', 'iss', 'cloud_instance_name', 'cloud_instance_host_name', 'cloud_graph_host_name', 'msgraph_host', 'aud', 'exp', 'iat', 'auth_time', 'acr', 'nonce', 'preferred_username', 'name', 'tid', 'ver', 'at_hash', 'c_hash', 'email'], 'kerberos_endpoint': 'https://login.microsoftonline.com/7448cd93-a4af-42bc-a76b-890ed150f1b7/kerberos', 'tenant_region_scope': 'NA', 'cloud_instance_name': 'microsoftonline.com', 'cloud_graph_host_name': 'graph.windows.net', 'msgraph_host': 'graph.microsoft.com', 'rbac_url': 'https://pas.windows.net'}
Broker enabled? None
Generate or reuse correlation_id: 455cc
https://login.microsoftonline.com:443 "POST /oauth2/v2.0/token HTTP/1.1" 200 5025
event={
"client_id": "5dg314--546456cf0403xxxx",
"data": {
"claims": null,
"code": "jhgkj
"code_verifier": "756868N",
"redirect_uri": "http://localhost:8000/microsoft_sso/callback/",
"scope": [
"openid",
"profile",
"User.Read",
"email",
"offline_access"
]
},
"environment": "login.microsoftonline.com",
"grant_type": "authorization_code",
"params": null,
"response": {
"access_token": "********",
"client_info": "
"expires_in": 5178,
"ext_expires_in": 5178,
"id_token": "********",
"refresh_token": "********",
"scope": "email openid profile User.Read",
"token_type": "Bearer"
},
"scope": [
"email",
"openid",
"profile",
"User.Read"
],
"token_endpoint": "https://login.microsoftonline.com/3456/oauth2/v2.0/token"
}
load_ssl_context verify=True cert=None trust_env=True http2=False
load_verify_locations cafile='C:\\Users\\Vinodh\\My Repo\\Vetting App\\Lib\\site-packages\\certifi\\cacert.pem'
connect_tcp.started host='graph.microsoft.com' port=443 local_address=None timeout=5.0 socket_options=None
connect_tcp.complete return_value=<httpcore._backends.sync.SyncStream object at 0x000002F4731v50>
start_tls.started ssl_context=<ssl.SSLContext object at 0760> server_hostname='graph.microsoft.com' timeout=5.0
start_tls.complete return_value=<httpcore._backends.sync.SyncStream object at 0x000002F4v84C20>
send_request_headers.started request=<Request [b'GET']>
send_request_headers.complete
send_request_body.started request=<Request [b'GET']>
send_request_body.complete
receive_response_headers.started request=<Request [b'GET']>
receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Cache-Control', b'no-cache'), (b'Transfer-Encoding', b'chunked'), (b'Content-Type', b'application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8'), (b'Content-Encoding', b'gzip'), (b'Vary', b'Accept-Encoding'), (b'Strict-Transport-Security', b'max-age=31536000'), (b'request-id', 65'), (b'client-request-id',7), (b'x-ms-ags-diagnostic', b'{"ServerInfo":{"DataCenter":"South Central
HTTP Request: GET https://graph.microsoft.com/v1.0/me "HTTP/1.1 200 OK"
receive_response_body.started request=<Request [b'GET']>
receive_response_body.complete
response_closed.started
response_closed.complete
close.started
close.complete
load_ssl_context verify=True cert=None trust_env=True http2=False
load_verify_locations cafile='C:\\Users\\Vinodh\\My Repo\\Vetting App\\Lib\\site-packages\\certifi\\cacert.pem'
connect_tcp.started host='graph.microsoft.com' port=443 local_address=None timeout=5.0 socket_options=None
connect_tcp.complete return_value=<httpcore._backends.sync.SyncStream object at 0x000002F47327D2E0>
start_tls.started ssl_context=<ssl.SSLContext object at 06575B5D0> server_hostname='graph.microsoft.com' timeout=5.0
start_tls.complete return_value=<httpcore._backends.sync.SyncStream object at 67F>
send_request_headers.started request=<Request [b'GET']>
send_request_headers.complete
send_request_body.started request=<Request [b'GET']>
send_request_body.complete
receive_response_headers.started request=<Request [b'GET']>
receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Cache-Control', b'no-cache'), (b'Transfer-Encoding', b'chunked'), (b'Content-Type', b'application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8'), (b'Content-Encoding', b'gzip'), (b'Vary', b'Accept-Encoding'), (b'Strict-Transport-Security', b'max-age=31536000'), (b'request-id', 7), (b'client-request-id',767'), (b'x-ms-ags-diagnostic', b'{"ServerInfo":{"DataCenter":"South Central
HTTP Request: GET https://graph.microsoft.com/v1.0/userfgujjkila4dfff?$select=mailVerified "HTTP/1.1 200 OK"
receive_response_body.started request=<Request [b'GET']>
receive_response_body.complete
response_closed.started
response_closed.complete
close.started
close.complete
load_ssl_context verify=True cert=None trust_env=True http2=False
load_verify_locations cafile='C:\\Users\\VinodhTandrothu\\My Repo\\Vetting App\\Lib\\site-packages\\certifi\\cacert.pem'
connect_tcp.started host='graph.microsoft.com' port=443 local_address=None timeout=5.0 socket_options=None
connect_tcp.complete return_value=<httpcore._backends.sync.SyncStream object at 0x00fghj350>
start_tls.started ssl_context=<ssl.SSLContext object at 0x000002F47336F9D0> server_hostname='graph.microsoft.com' timeout=5.0
start_tls.complete return_value=<httpcore._backends.sync.SyncStream object at 0xfghj0>
send_request_headers.started request=<Request [b'GET']>
send_request_headers.complete
send_request_body.started request=<Request [b'GET']>
send_request_body.complete
receive_response_headers.started request=<Request [b'GET']>
receive_response_headers.complete return_value=(b'HTTP/1.1', 404, b'Not Found', [(b'Transfer-Encoding', b'chunked'), (b'Content-Type', b'application/json'), (b'Content-Encoding', b'gzip'), (b'Vary', b'Accept-Encoding'), (b'Strict-Transport-Security', b'max-age=31536000'), (b'request-id', b'64dfghj1'), (b'client-request-id', 66'), (b'x-ms-ags-diagnostic', b'{"ServerInfo":{"DataCenter":"South Central
HTTP Request: GET https://graph.microsoft.com/v1.0/me/photo/$value "HTTP/1.1 404 Not Found"
receive_response_body.started request=<Request [b'GET']>
receive_response_body.complete
response_closed.started
response_closed.complete
close.started
close.complete
Page /microsoft_sso/callback/ took 3.1010 seconds to load.
"GET /microsoft_sso/callback/?code=0.AX0dfgh2kfit0&state=64vbg3a0-8fe5-4826-a3f4-bca7548c67d5&session_state=56xxx HTTP/1.1" 302 0
h-&state=643xxxx&session_state=56xxxbe-xxxx HTTP/1.1" 302 0
Page /admin/ took 0.0046 seconds to load.
"GET /admin/ HTTP/1.1" 302 0
"GET /admin/ HTTP/1.1" 302 0
Page /admin/login/ took 0.0057 seconds to load.
"GET /admin/login/?next=/admin/ HTTP/1.1" 200 16651
"GET /admin/login/?next=/admin/ HTTP/1.1" 200 16651
"GET /static/admin/css/base.css HTTP/1.1" 304 0
"GET /static/admin/css/base.css HTTP/1.1" 304 0
"GET /static/admin/css/login.css HTTP/1.1" 304 0
"GET /static/admin/css/login.css HTTP/1.1" 304 0
Hi, @vinodhkumartandrothu , thanks for the message. Regarding the two issues mentioned:
I can't reproduce, but it's possible this is related with some silent error on django handling the already populated user database you mentioned, which stops the framework to process the callback view. If this behavior still occurs, my suggestion is to debug the django_microsoft_sso/views.py
file to better find the error context.
This occurs when user data was received from Microsoft but it's not created or found in database. I think this is because 1) MICROSOFT_SSO_AUTO_CREATE_USERS
is disabled, as you stated and 2) User was not found using their User Principal Name (or Mail if you set the MICROSOFT_SSO_UNIQUE_EMAIL
option). If you're using a Custom User Authentication, make sure your USERNAME_FIELD
is correct configured on your custom model.
I push a new version with a new option: MICROSOFT_SSO_SHOW_FAILED_LOGIN_MESSAGE
. When enabled, you will see the failed login attempt reason on browser. And this message will be always logged on terminal for now on.
Please add the MICROSOFT_SSO_SHOW_FAILED_LOGIN_MESSAGE=True
on your settings.py and let me now if this can help fix this issue. New version is 4.1.0.
Hi @chrismaille Thank you for the new version of the package. It has been very helpful in debugging login issues. I have successfully tested the Microsoft SSO button for superusers, who can now log in to the admin panel, and I see data populating in the microsoft_sso_user table.
I have also developed a custom SSO button for our web application because the default button is only visible on the admin page. However, I am encountering an issue when logging into our web app as staff users or regular users through this custom SSO button. Even though these users exist in the database, I receive a "User not found" error. I'm encountering an issue with the Microsoft SSO integration. Regardless of whether I log in as a superuser, staff user, or regular user on my web app's home page, the system always redirects me to the admin page after a successful login (currently login is working for superusers). Below are the relevant logs:
2024-09-19 13:26:53.636 | INFO | xxxx.backend:pre_create_callback:162 - Pre-create callback skipped, user creation is disabled.
2024-09-19 13:26:53.868 | WARNING | django_microsoft_sso.utils:send_message:8 - User not found - UPN: 'testuser2@xxx.com', Email: 'None'. Auto-Create is disabled.
2024-09-20 14:42:53.594 | DEBUG | xxx.backend:pre_validate_callback:490 - Running Pre-Validate callback for email/UPN: testuser1@xxx.com.
2024-09-20 14:42:53.834 | INFO | xxx.backend:pre_validate_callback:496 - User testuser1@xxx.com exists in the local database.
2024-09-20 14:42:53.834 | INFO | xxx.backend:pre_create_callback:507 - Pre-create callback skipped, user creation is disabled.
2024-09-20 14:42:53.864 | WARNING | django_microsoft_sso.utils:send_message:8 - User not found - UPN: 'testuser1@xxx.com', Email: 'None'. Auto-Create is disabled.
I have intentionally disabled automatic user creation, as I only want to log in users who already exist in our system.
Our setup includes superusers, staff users, and regular users in the database. While all users should be able to log in through the SSO button, only staff users and superusers should be able to access the Django Admin page. I don't want to flag all users as staff, as their admin access should be based on their existing roles and permissions.
Could you please help me to integrate SSO button for all users irrespective of staff status or does it work only for superusers and staff users
The logs suggest the azure user with UPN testuser2@xxx.com
was not found. The package use this code to search for user when auto creation is disabled: https://github.com/megalus/django-microsoft-sso/blob/65168bbf80693d7714c53a51de95eb8fae6b1e30/django_microsoft_sso/main.py#L287
If you're using a Custom Authentication, please check if the USERNAME_FIELD
is correct set to the UPN field in your model. Something like this:
class MyUser(AbstractBaseUser):
my_upn_field = models.CharField(max_length=40, unique=True) # <- the field you store User Principal Names (UPN)
name= models.CharField(max_length=40)
...
USERNAME_FIELD = "my_upn_field" # <- add here
I am using the default Django User model with no custom authentication. Users already exist in the database with matching emails, but I’m still encountering a "User Not Found" error during Microsoft SSO login.
The logs indicate that the Azure user with UPN (e.g., testuser1@domain.com) was not found. My MICROSOFT_SSO_UNIQUE_EMAIL is set to True.
Regardless of whether I log in as a staff user, or regular user on my web app's home page using SSO button, the system always redirects me to the admin page after User not found error.
UPN
and Mail
are different things in Azure. If your log are showing this:
2024-09-20 14:42:53.864 | WARNING | django_microsoft_sso.utils:send_message:8 - User not found - UPN: 'testuser1@xxx.com', Email: 'None'. Auto-Create is disabled.
This means the information retrieved from Microsoft Graph are:
{
"userPrincipalName": "testuser1@xxx.com",
"mail": null,
}
When MICROSOFT_SSO_UNIQUE_EMAIL
is True
the package will compare the mail
field from Graph API against the email
field from User model. But because mail
is empty, the user will never be found.
My advice is to set the MICROSOFT_SSO_UNIQUE_EMAIL=False
and let the package compare the userPrincipalName
received against the USERNAME_FIELD
on your model. If you're using the default user model, this is the username
field.
Please, let me know if this help to fix the issue.
Thanks for your prompt response. I tried setting MICROSOFT_SSO_UNIQUE_EMAIL=False, but still the error persists with User Not Found.
Regardless of whether I log in as a staff user, or regular user on my web app's home page using SSO button, the system always redirects me to the admin page after User not found error.
I wanted to follow up regarding the issue last week. I tried setting MICROSOFT_SSO_UNIQUE_EMAIL=False as per your suggestion, but unfortunately, I’m still encountering the "User Not Found" error.
Regardless of whether I log in as a staff user or a regular user via the SSO button on my web app’s home page, the system redirects me to the admin page after the error.
Is there anything else I should update to resolve this issue? I’d appreciate any further guidance you could provide.
Thanks again for your help!
Hi @vinodhkumartandrothu, about the questions:
It's difficult to say, because it depends on the actual database structure. The best advice I can make is to make sure this code works for your users database: https://github.com/megalus/django-microsoft-sso/blob/65168bbf80693d7714c53a51de95eb8fae6b1e30/django_microsoft_sso/main.py#L287
Let me reproduce here:
def find_user(self):
if conf.MICROSOFT_SSO_UNIQUE_EMAIL: # <- Set this to False
query = self.user_model.objects.filter(email__iexact=self.user_email)
else:
username_query = {
f"{self.username_field.attname}__iexact": self.user_principal_name # <- Make sure the `username field` on your database is the USERNAME_FIELD of the model
}
query = self.user_model.objects.filter(
Q(microsoftssouser__user_principal_name__iexact=self.user_principal_name) # <- will not work, because you are not creating users
| Q(**username_query)
)
if query.exists():
return query.get()
The USERNAME_FIELD
is the key here. If you have something like this on your database:
class MyUser(AbstractBaseUser):
identifier = models.CharField(max_length=40, unique=True) # <- if this is field you store the User Principal Name you got from Microsoft Graph
...
USERNAME_FIELD = "identifier" # <- Then this is the field you need to define here.
If this not help, my suggestion is to rewrite the find_user
method in a fork, to best match your database structure.
User not Found
issueThe package will redirect the user to the route defined in MICROSOFT_SSO_LOGIN_FAILED_URL
. Default is admin:index
. You need to change this option to the route name you want to redirect the user to another page.
This issue has been marked as stale due to lack of activity. It will be closed in 7 days if no further activity occurs.
Django Microsoft SSO not working and site cannot be reached or redirected back to the admin login page (looping without successful login) at
http://localhost:8000/microsoft_sso/callback/?code=0.AW8Bdq0dh0K3-km8RSyHvV9bYkME2G7dNWhAp9xtpk9VIMlvAQA.AgABBAIAAAApTwJmzXqdR4BN2miheQMYAwDs_wUA9P_cCeWTUEuL_3GAxw2pLR3yopUhdJKxKur6SFer5Mbi4Uf8Z0HTxttwsJv8jeqy1zIe0xows6UVIgb_w1wOsjzuhiyUWHTQt-dbOE9ZEhZ5rf_spYcEMRyOmqxOZP3snDSqnfutGIae3xrHo9tRGIbigbCsvvcjWvHhg1ATPG5n4SAcpHWf65B7KraWrI-1L0ngrL9kWvh8f38I8EM0RKvGYHqS-KWR86pPKWXdcXFKdlkh4FRLrdS_VURknXDjaKh5q_kqXoCDnhfAnvteiyM5_lkdYKLAh3orD8rn1PIMv4Qf4B52MPTl33hv7-jVoq_93uf8l8HDhRrECvjU7LxjQZhPUPNEa50kZ56JasVp1Eg2oWfYqFCsxQSB5iHePRwsENSu8NUTFWFhRuWrfNXkw2xEAiHOZx8EpA0djNmaawBfxS0o3xJhRnn5kzFAYxj1mCUO9tLS63GYKQbZa_nQ8LacADanknRjVwJnelMHuSBrT8N3PP-wSB7pcvJtZJnGz5AheNg5yvi1hj-F0iK3It5WfPGRcy8mBkSDDjXOtJJKJov_s-PBTIF7_kW46jhhntlV3BSgv1G_lukt4PH8bzgWv_A9AbMC43JLIxoiEDJBIsOMn3XKlfgjAyB2-pgnlFf5zsiHqj64as7-IgRwcAMn9QYYy52qQqkiJQSnJ_27jmd-ipVikvtffE4k6QLl23-4sdNMH3RdsyztfJLTVI4n3fmiRB6L5bzu_srvu0gTl2kbw_Ch-zuX8m-DzxWQ16885oAG1Lk7B0LGXeIrGk-Wby_XAXx9XBFz7J0SA1REe4Byw_ZYXzqv3HeIEqJw9w3wNV8dxBc_W1wzfz0FqRCgyoeWRkAOZ7V6_HpheiDK8VUcpbN56axOICRxccVTH-Swy3MNEmtB1xemk3XBgvVmVOD3DMSaVn4LH7o0d8tcmNCnQt2k6-KOX_-mMFjNddZ3Le2y-FJmYP-6QKAb2LR_GWZ_5XlA0Kfqa2Abp0Sh2PtNCQG7C7FllFrvj0McElogGd2AFGi4jpmAzVy2l03CBBOVJ7L76fwHOSjy15BhbalHitzopbaTF4MaTLvWImEHiqipZavk3E0tfoMh2cZjuQHP9eNescB69Di9LzQeOsJHMcBZaytnvW3mXCYSQrOYJXgPx6oXUIjiu3EogMqmMXgexEtRzNs0XY5D09pgRYSob86ohiZiy5KKc_FoABHDU1s_KNa_woBEVgeV5374DeqMREXYwyRNKBELEhgz2zKLeBfPT8-dLbsbFL7a3GrobEawd48GVxmu0r-uA1D0z3alqIWboymWnqgRyxMmmtYe65QqfeDYW0ZaCfEMpWp4XyXic-lIzJbL6hKefGfxC7e3h-Y&client_info=eyJ1aWQiOiIwMDAwMDAwMC0wMDAwLTAwMDAtOWQ4YS05MGQ2MWQ0NzM4ZGEiLCJ1dGlkIjoiOTE4ODA0MGQtNmM2Ny00YzViLWIxMTItMzZhMzA0YjY2ZGFkIn0&state=18109584-3108-4050-9fcf-4aea13f3d828&session_state=139d2609-f5f0-4a82-b96b-599f4f350aff#
Please see the logs below Logs:
Server is running on http://localhost:8000/ and I will create an issue under original repo. Please see the logs above and please help me out.
I've set MICROSOFT_SSO_AUTO_CREATE_USERS = False in my settings.py file because I already have an existing user database, and I do not want the system to automatically create new users.
However, when I attempt to log in with these existing users, one of the following happens: I am redirected back to the admin login page (looping without successful login) or I receive a "Site cannot be reached" error.
path( "microsoft_sso/", include("django_microsoft_sso.urls", namespace="django_microsoft_sso"), ),
I have refered below links and did as per the guidelines.
https://pypi.org/project/django-microsoft-sso/ https://megalus.github.io/django-microsoft-sso/callback/
Refer the file which are required to review:
example_microsoft_app/settings.py https://github.com/vinodhkumartandrothu/django_microsoft_sso/blob/main/example_microsoft_app/urls.py https://github.com/vinodhkumartandrothu/django_microsoft_sso/blob/main/example_microsoft_app/.env