Giter Site home page Giter Site logo

angellusmortis / django_microsoft_auth Goto Github PK

View Code? Open in Web Editor NEW
137.0 137.0 83.0 499 KB

Simple app to enable Microsoft Account, Office 365 and Xbox Live authentcation as a Django authentcation backend.

License: MIT License

Python 87.49% CSS 0.16% JavaScript 4.15% HTML 4.86% Shell 2.52% Dockerfile 0.81%

django_microsoft_auth's People

Contributors

7oi avatar angellusmortis avatar aviv-ebates avatar califlower avatar chenbr avatar dependabot[bot] avatar filipbec avatar georgethomasuk avatar hackedhead avatar hazraa avatar jessedeloore avatar jordanreiter avatar kangasta avatar korverdev avatar ldelagarde avatar pyup-bot avatar rodneymandap avatar sagarc03 avatar thecyberfox avatar wckd avatar yeago avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django_microsoft_auth's Issues

error: "bad_state"

  • Django Microsoft Authentication Backend version: django-microsoft-auth-1.1.1 oauthlib-2.1.0 requests-oauthlib-1.0.0
  • Python version: Python 3.5.3 (default, Jan 19 2017, 14:11:04)
  • Operating System: 4.9.0-8-amd64 #1 SMP Debian 4.9.110-3+deb9u5 (2018-09-30) x86_64 GNU/Linux

Description

Followed instructions for install.
Redirect failing with error.

Object { error_description: "An invalid state variable was provided. Please refresh the page and try again later.", error: "bad_state" }

What I Did

Followed instructions for install.
Initially, I didn't have sites framework installed. So installed:

Add 'django.contrib.sites' to your INSTALLED_APPS setting.
Define a SITE_ID setting:
SITE_ID = 1

/admin/sites/site/1/change/ if you have the admin site enabled.

Also, noticed after doing this, the incorrect URL was appearing in the 'authorization_url':

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?response_type=code&client_id=cf28bef5-aa4d-41ac-89be-dc5c06f959e1&redirect_uri=https%3A%2F%2Fexample.com%2Fmicrosoft%2Fauth-callback%2F&scope=User.Read&state=cqHo4wstRvs8L2UiEN3F7NUGnpE0x29uzqTfPHBfP3THFW0Wwtiw05kw5mBJ6f6I&response_mode=form_post'});

I followed steps here: https://docs.djangoproject.com/en/1.11/ref/contrib/sites/#caching-the-current-site-object

After restarting the app, this resolved the issue.
URL was correct after restart.

Followed steps here:
8. Start site and goto /admin to and logout if you are logged in.
9. Login as Microsoft/Office 365/Xbox Live user. It will fail. This will automatically create your new user.

Login did fail, but a user was never created.
I continued on with step 10 and logged in with a password user (superuser).
( This is where I noticed that user had not been created).
I manually added 0365 user under "Microsoft accounts".
Logged out of admin after this.

I then attempted to login:
Getting this error when trying to login with "Microsoft" button.
Pop-up box appears for MS authentication.
Login to O365 (with user added to admin).
Redirect takes place, to /microsoft/auth-callback/, in popup, but prints this message:

error: "bad_state"
error_description: "An invalid state variable was provided. Please refresh the page and try again later."

Then popup closes immediately.
Text is added to login box:
capture

Looking at daphne logs, I can see the request taking place for the redirect.

"POST /microsoft/auth-callback/ HTTP/1.1" 400 665 "https://login.microsoftonline.com/common/reprocess?ctx=rQIIAdNiNtIzsFJJTjO..........." "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0"

Any ideas?

Allow use of multiple sites via `self.request`

  • Django Microsoft Authentication Backend version: 1.3.0
  • Python version: 3.6.7
  • Operating System: ubuntu 18.05

Description

We have a site with multiple URLs (e.g., one for private-facing, one for public-facing). we should be able to login using all of the urls). This can be fixed by passing self.request into the call to Site.objects.get_current which will allow us to configure multiple sites rather than allowing us to specify only one SITE_ID.

Scope has changed from "email openid" to "profile email openid".

  • Django Microsoft Authentication Backend version:Django Version: 2.1.7
  • Python version: 3.6.8
  • Operating System:LINUX
  • Browser and version you are testing in:Chrome
  • What browser plugins do you have installed that may interfere with cookies or Javascript:

Description

Describe what you were trying to get done.
Tell us what happened, what went wrong, and what you expected to happen.

What I Did

I get this error when I try to login
Scope has changed from "email openid" to "profile email openid".
Can I do something?

/admin/login/?next=/admin/ won't redirect when logging in with microsoft credentials

When I navigate to /admin/login/?next=/admin/ and log in with
an existing username and password I get logged in and redirected to the admin panel.

However, when I log in with my microsoft credentials, I can successfully create and log in a user but I don't get redirected, it just stays on the same page.

I know the user has been created and logged in correctly because if I then navigate to /admin I am logged in as that user.

Any ideas how I can get the redirect to work ?

The exception thrown for sqlite3 db is different than one thrown for mysql

  • Django Microsoft Authentication Backend version: 2.3.0
  • Django version: 2.2.3
  • Python version: 3.7.2
  • Operating System: macOS 10.14.5

Description

After following the description at https://django-microsoft-auth.readthedocs.io/en/latest/usage.html to setup the library, running python manage.py migrate gives me the error:

django.db.utils.ProgrammingError: (1146, "Table 'mydatabase.django_site' doesn't exist")

In this project configuration, I am using MySQL instead of the default sqlite3.

Steps to Reproduce

Possible Solution

At https://github.com/AngellusMortis/django_microsoft_auth/blob/master/microsoft_auth/apps.py#L41, it's catching OperationalError. Django configured with MySQL returns the exception django.db.utils.ProgrammingError. It might best to also catch it there:

from django.db.utils import ProgrammingError

except (OperationalError, ProgrammingError):

Migrations for microsoft_id field are not synchronized with models.py

  • Django Microsoft Authentication Backend version: 1.2.0
  • Python version: 3.6
  • Operating System: Ubuntu 16.04

Description

Migrations file has microsoft_id field as max_length 32 and models.py have it as max_length=36.
I can't login with Office365 account because it says microsoft_id column is not big enough.

What I Did

$ ./manage.py makemigrations
Migrations for 'microsoft_auth':
  /usr/local/lib/python3.6/site-packages/microsoft_auth/migrations/0002_auto_20190228_2006.py
    - Alter field microsoft_id on microsoftaccount
$ ./manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, catalog, contenttypes, microsoft_auth, risk_management, sessions, sites
Running migrations:
  Applying microsoft_auth.0002_auto_20190228_2006... OK

this fixes the issue, but would be better if migration was in the repo in the first place

What is the proper way of passing claims on authorization?

First of, thanks for a great library!

I have a question, I want to run custom code based on user claims on user authorization, right now the only way I see it (without extending / modifying the library).

  • Create the hook "MICROSOFT_AUTH_AUTHENTICATE_HOOK"
  • Retrieve the token in that hook
  • Generate a public_key
  • Retrieve claims by combining token/public key and run a decode

Am I missing something, is there a easier way?

Currently I have experimented with building my own backend that extends upon MicrosoftAuthenticationBackend, which in the end makes sure the hook gets the claims. But I would love to have a easier solution :)

Thanks!
/Martin

Custom UserAdmin is overrided when django_microsoft_auth is included as last app in django settings

When microsoft_auth is included after custom apps in INSTALLED_APPS then custom UserAdmin is overridden by default UserAdmin.

Step to reproduce:

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "myapp",
    "microsoft_auth"
]

In myapp admin.py:

admin.site.register(User, MyCustomUserAdmin)

Code in: https://github.com/AngellusMortis/django_microsoft_auth/blob/master/microsoft_auth/admin.py#L33
will replace MyCustomUserAdmin back to UserAdmin.

Pip install - No module named 'pip.req'

  • Django Microsoft Authentication Backend version: 1.0.6
  • Python version: 3.6.5
  • Operating System: Archlinux

Description

I would like to install your package with pip (like in your README.md), but the setup script cannot find the package pip.req.

What I Did

shigumitsu@shiguarch $> pip install django_microsoft_auth

Collecting django_microsoft_auth
  Using cached https://files.pythonhosted.org/packages/b2/b2/ad16fb5d39df00f476999e7977cfb9546d2dff1eecbb8fe1ad8e6225079f/django_microsoft_auth-1.0.6.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-fz2vh467/django-microsoft-auth/setup.py", line 8, in <module>
        from pip.req import parse_requirements
    ModuleNotFoundError: No module named 'pip.req'

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-fz2vh467/django-microsoft-auth/

Initial Update

Hi 👊

This is my first visit to this fine repo, but it seems you have been working hard to keep all dependencies updated so far.

Once you have closed this issue, I'll create separate pull requests for every update as soon as I find one.

That's it for now!

Happy merging! 🤖

Application is not configured as a multi-tenant application

  • Django Microsoft Authentication Backend version: 2.2.1
  • Python version: 3.6.7
  • Operating System: Ubuntu 18.04
  • Browser and version you are testing in: Mozilla Firefox 66.0.3
  • What browser plugins do you have installed that may interfere with cookies or Javascript: -

Description

I got the following message from the Microsoft Server: https://login.microsoftonline.com/common/oauth2/v2.0/authorize...

Sign in

Sorry, but we’re having trouble with signing you in.
AADSTS50194: Application '***' is not configured as a multi-tenant application. Usage of the /common endpoint is not supported for such applications created after '10/15/2018'. Use a tenant-specific endpoint or configure the application to be multi-tenant.

Is this a know issue?

Getting 400 Bad Request for POST /microsoft/auth-callback/

  • Django Microsoft Authentication Backend version: 1.1.1
  • Python version: 3.6.6
  • Operating System: Ubuntu 18.04 LTS

Description

{'code': '...removed for brevity...', 'state': '...removed for brevity...', 'session_state': '...removed for brevity...'}
Bad Request: /microsoft/auth-callback/
[01/Nov/2018 11:14:24] "POST /microsoft/auth-callback/ HTTP/1.1" 400 668

Any ideas what I'm doing wrong ?

Heroku Deploy

Hi There,

I’ve trying to get my website up and running for the last couple days and can’t see to figure out what’s going on.

When I run the app locally and go to the admin page I see a button for Windows and Password as expected. When I click on Windows I get a popup saying the redirect_uri doesn’t match which is also expected since it’s http vs https.

When I deploy onto Heroku the app loads fine and so does the admin page but when I click the Windows button nothing happens and I don’t think it’s becuase a popup is being blocked.

Do I need to make a sign in page and if so what’s the best way to do that? All I need is authentication so that I can build a company intranet but really struggling.

Any help is greatly appreciated!

the package on pypi doesn't include the templates or static media

  • Django Microsoft Authentication Backend version: 1.0.4
  • Python version: 3.5.3
  • Operating System: Debian Stretch

Description

After running: pip install django_microsoft_auth, I followed the README. When I got to the admin loging step, I got an Django error page saying that microsoft/admin_login.html wasn't found. When I went fishing thought my site-packages I confirmed that it wasn't there. Also the static files(js, etc) aren't there.

When I pip installed from github: pip install -e git+https://github.com/AngellusMortis/django_microsoft_auth.git#egg=microsoft_auth, all works fine. I suggest including templates and static media in the pypi package just like Django itself does.

Redirect to another page (not admin) and logout

Django Microsoft Authentication Backend version: 2.2.3

Django version: 2.2.1

Python version: 3.6.8

Operating System: Ubuntu 18.04

Description
Hi.

I'm trying to create an app using django_microsoft_auth as backend for login and logout, however I could not redirect to another page (not admin) like dashboard or index. And here is another question. How is the procedure for logout?

Could you help me with those things?

Best regards.

Oscar Alvarez

Create user with is_staff=True

Hello!

After the first login, the user logs into the admin. That is, the user is created with is_staff=True. It would have been very comfortable.

Setting Call back function after successful authentication

  • Django Microsoft Authentication Backend version:0.6.1
  • Python version:3.7.1
  • Operating System:Windows 10 Pro
  • Browser and version you are testing in: Chrome
  • What browser plugins do you have installed that may interfere with cookies or Javascript:Several

Description

I have installed plugin successfully and it works great.
What I would like to do is assigning a default role to the Microsoft authenticated user on first successful authentication.
How can I configure a function as a callback function after successful authentication?

What I Did

Not applicable.

Cache.Get Fails to Get Default Value

  • Django Microsoft Authentication Backend version: 2.3.1
  • Django version: 3.0.5
  • Python version: 3.7.6
  • Operating System: Linux
  • Browser and version: Any
  • Browser extensions/plugins you have installed: N/A

Description

After implementing caching on Heroku used memcached, I was unable to login. Every login attempt returned a 500 error.

Logs showed the error was "unable to get len for jwks of NoneType"

The line of code in question is in client.py:
jwks = cache.get(CACHE_KEY_JWKS, [])

Based on this issue reported for django-bmemcached, apparently bmemcached does not return a default value. While technically this should be addressed by bmemcached, it's a simple workaround in the code.

I messed up and didn't create a separate git branch to make a pull request when I made the fix but it's located here if you want to fix.

pip incompatibility

Traceback (most recent call last):
File "", line 1, in
File "/tmp/pip-install-gb2iu7r4/django-microsoft-auth/setup.py", line 39, in
requirements[req] = [str(req.req) for req in reqs]
File "/tmp/pip-install-gb2iu7r4/django-microsoft-auth/setup.py", line 39, in
requirements[req] = [str(req.req) for req in reqs]
AttributeError: 'ParsedRequirement' object has no attribute 'req'

Scope has changed from "openid profile email" to "openid email User.Read profile".

Good evening I'm having issues when trying to use the django_microsoft_auth. Upon selecting the microsoft user to login I'm getting the below error during POST request.

Environment:

Request Method: POST
Request URL: http://localhost:8000/microsoft/auth-callback/

Django Version: 3.0.4
Python Version: 3.8.2
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'homepage',
'financerecords',
'financetransaction',
'easy_thumbnails',
'image_cropping',
'bootstrap4',
'bootstrap_datepicker_plus',
'django_cleanup',
'django.contrib.sites',
'microsoft_auth']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']

Traceback (most recent call last):
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\django\core\handlers\base.py", line 115, in get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\bren
\PycharmProjects\SZPMSite\venv\lib\site-packages\django\core\handlers\base.py", line 113, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\bren
\PycharmProjects\SZPMSite\venv\lib\site-packages\django\views\generic\base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\django\utils\decorators.py", line 43, in wrapper
return bound_method(*args, **kwargs)
File "C:\Users\bren
\PycharmProjects\SZPMSite\venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\microsoft_auth\views.py", line 47, in dispatch
return super().dispatch(request, *args, **kwargs)
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\django\views\generic\base.py", line 97, in dispatch
return handler(request, *args, **kwargs)
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\microsoft_auth\views.py", line 145, in post
context = self.get_context_data(**request.POST.dict())
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\microsoft_auth\views.py", line 68, in get_context_data
self.authenticate(kwargs.get("code"))
File "C:\Users\bren
\PycharmProjects\SZPMSite\venv\lib\site-packages\microsoft_auth\views.py", line 129, in authenticate
user = authenticate(self.request, code=code)
File "C:\Users\bren
\PycharmProjects\SZPMSite\venv\lib\site-packages\django\contrib\auth_init_.py", line 72, in authenticate
user = backend.authenticate(request, **credentials)
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\microsoft_auth\backends.py", line 43, in authenticate
token = self.microsoft.fetch_token(code=code)
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\microsoft_auth\client.py", line 169, in fetch_token
return super().fetch_token( # pragma: no cover
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\requests_oauthlib\oauth2_session.py", line 360, in fetch_token
self.client.parse_request_body_response(r.text, scope=self.scope)
File "C:\Users\bren
\PycharmProjects\SZPMSite\venv\lib\site-packages\oauthlib\oauth2\rfc6749\clients\base.py", line 421, in parse_request_body_response
self.token = parse_token_response(body, scope=scope)
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\oauthlib\oauth2\rfc6749\parameters.py", line 431, in parse_token_response
validate_token_parameters(params)
File "C:\Users\bren_\PycharmProjects\SZPMSite\venv\lib\site-packages\oauthlib\oauth2\rfc6749\parameters.py", line 461, in validate_token_parameters
raise w

Exception Type: Warning at /microsoft/auth-callback/
Exception Value: Scope has changed from "openid profile email" to "openid email User.Read profile".

In settings.py in Django I'm including:
MICROSOFT_AUTH_CLIENT_ID
MICROSOFT_AUTH_TENANT_ID
MICROSOFT_AUTH_CLIENT_SECRET
MICROSOFT_AUTH_LOGIN_TYPE = 'ma'

In templates - Options - context_processors I'm including 'microsoft_auth.context_processors.microsoft',

and in the Installed APPS I'm including the
'django.contrib.sites',
'microsoft_auth',

I'm quite new to django and authentication with Microsoft, so can you kindly advise what I'm doing wrong?

Thanks

Using django_microsoft_auth with Django Rest Framework

Django Microsoft Authentication Backend version: 1.3.0
Python version: 3.7
Django Version: 2.1.7
Operating System: Windows 10 Enterprise
Google Chrome Version 72.0.3626.121
Chrome Extensions:

Ublock Origin
Laspass
Todoist

Description

Has anyone successfully used this library with Django Rest Framework yet? I am looking to implement it, and can write documentation for the docs once I do it. I was curious if anyone had done so already or had any suggestions. Also, are issues the appropriate way to ask this?

Inability to use a single tenant app registration.

Has anyone worked around this?

  • Django Microsoft Authentication Backend version: 2.3.1
  • Django version: 3.0
  • Python version: 3.6
  • Operating System: CentOS, Windows 10
  • Browser and version: Brave, Chrome, Firefox -- all latest.
  • Browser extensions/plugins installed: N/A

Description

When using the keys for an app registration that is only permissable for a single tenant the callbacks don't work and it won't authenticate. It will raise an error because the endpoint for a multi-tenant app registration is different than the single tenant flavor.

Environment Setup Steps

Create blank django with this package and django admin.
Add keys for single tenant Azure app registration.
Try to login, get DEBUG 500 server error due to improper callback response due to incorrect url.

Errors installing on pip 19.x in dev mode

Description

Installing in dev mode (pip install -e ".[dev]" or `pip install -e /path/to/this/repo/) using pip 19.x throws errors.

19.2.6

  ERROR: Command errored out with exit status 1:
   command: /home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/bin/python3.6 /home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py get_requires_for_build_wheel /tmp/tmpv3c5rj6j
       cwd: /home/levy/code/django_microsoft_auth
  Complete output (25 lines):
  Traceback (most recent call last):
    File "setup.py", line 14, in <module>
      from pip._internal.req import parse_requirements
  ModuleNotFoundError: No module named 'pip'
  
  During handling of the above exception, another exception occurred:
  
  Traceback (most recent call last):
    File "/home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 207, in <module>
      main()
    File "/home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 197, in main
      json_out['return_val'] = hook(**hook_input['kwargs'])
    File "/home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 54, in get_requires_for_build_wheel
      return hook(config_settings)
    File "/tmp/pip-build-env-kd60gecg/overlay/lib/python3.6/site-packages/setuptools/build_meta.py", line 146, in get_requires_for_build_wheel
      return self._get_build_requires(config_settings, requirements=['wheel'])
    File "/tmp/pip-build-env-kd60gecg/overlay/lib/python3.6/site-packages/setuptools/build_meta.py", line 127, in _get_build_requires
      self.run_setup()
    File "/tmp/pip-build-env-kd60gecg/overlay/lib/python3.6/site-packages/setuptools/build_meta.py", line 237, in run_setup
      self).run_setup(setup_script=setup_script)
    File "/tmp/pip-build-env-kd60gecg/overlay/lib/python3.6/site-packages/setuptools/build_meta.py", line 142, in run_setup
      exec(compile(code, __file__, 'exec'), locals())
    File "setup.py", line 17, in <module>
      from pip.req import parse_requirements
  ModuleNotFoundError: No module named 'pip'
  ----------------------------------------
ERROR: Command errored out with exit status 1: /home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/bin/python3.6 /home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py get_requires_for_build_wheel /tmp/tmpv3c5rj6j Check the logs for full command output.

19.0.0

Obtaining file:///home/levy/code/django_microsoft_auth
  Installing build dependencies ... done
  Getting requirements to build wheel ... error
  Complete output from command /home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/bin/python3.6 /home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py get_requires_for_build_wheel /tmp/tmp_m06cp51:
  Traceback (most recent call last):
    File "/home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 207, in <module>
      main()
    File "/home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 197, in main
      json_out['return_val'] = hook(**hook_input['kwargs'])
    File "/home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 54, in get_requires_for_build_wheel
      return hook(config_settings)
    File "/tmp/pip-build-env-4ah3t_xv/overlay/lib/python3.6/site-packages/setuptools/build_meta.py", line 146, in get_requires_for_build_wheel
      return self._get_build_requires(config_settings, requirements=['wheel'])
    File "/tmp/pip-build-env-4ah3t_xv/overlay/lib/python3.6/site-packages/setuptools/build_meta.py", line 127, in _get_build_requires
      self.run_setup()
    File "/tmp/pip-build-env-4ah3t_xv/overlay/lib/python3.6/site-packages/setuptools/build_meta.py", line 142, in run_setup
      exec(compile(code, __file__, 'exec'), locals())
    File "setup.py", line 10, in <module>
      import versioneer
  ModuleNotFoundError: No module named 'versioneer'
  
  ----------------------------------------
Command "/home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/bin/python3.6 /home/levy/.pyenv/versions/3.6.8/envs/ruv-sso/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py get_requires_for_build_wheel /tmp/tmp_m06cp51" failed with error code 1 in /home/levy/code/django_microsoft_auth

Environment Setup Steps

I tried two versions of pip (19.2.6 and 19.0). Both fail but with different errors (see above). I use pyenv but it also raised the same errors using virtualenv python -m venv ....

Steps to Reproduce

clone the repo.

cd django_microsoft_auth
python3 -m venv venv
source venv/bin/activate
pip install -U pip==19.0 # or skip version to get latest pip, currently 19.2.6
pip install -e ".[dev]"

REDIRECT_URI going to example.com

Versions:
Django 3.0.6
django-microsoft-auth 2.3.1

the redirect uri that comes in the page source has "&redirect_uri=http%3A%2F%2Fexample.com%2Fmicrosoft%2Fauth-callback%2F&scope=openid+email+profile&state....."

my settings.py has all the usual suspects:

MICROSOFT_AUTH_CLIENT_ID =
MICROSOFT_AUTH_CLIENT_SECRET =
MICROSOFT_AUTH_TENANT_ID =

But grepping through the codebase I dont see any environment variables that it looks for the redirect uri. I only see it in the test_client.py where its explicitly set. Am i missing something?

STDOUT When started up:
Watching for file changes with StatReloader
Performing system checks...

System check identified some issues:

WARNINGS:
?: (microsoft_auth.W002) example.com is still a valid site, Microsoft auth might not work
HINT: Microsoft/Xbox auth uses OAuth, which requires a real redirect URI to come back to

System check identified 1 issue (0 silenced).
May 14, 2020 - 12:15:03
Django version 3.0.6, using settings 'mysite.settings'
Starting development server at http://0.0.0.0:13000/
Quit the server with CONTROL-C.

local variable 'jwk' referenced before assignment in client.py line 128

  • Django Microsoft Authentication Backend version: 2.3.1
  • Django version: 2.2.6
  • Python version: 3.7.4
  • Operating System: debian:buster-slim
  • Browser and version: Chromium 76.0.3809.132
  • Browser extensions/plugins you have installed:

Description

What happened?

The auth-callback received the POST request.

What went wrong?

UnboundLocalError at /microsoft/auth-callback/
local variable 'jwk' referenced before assignment
Exception Location: /usr/local/lib/python3.7/site-packages/microsoft_auth/client.py in get_claims, line 128

It seems kid from token does not match with key['kid'] and jwk remain undefined. jwk should be initialized with None before line 123 in microsoft_auth/client.py

Environment Setup Steps

Steps to Reproduce

Email issue when using Azure account

  • Django Microsoft Authentication Backend version: 2.2.3

  • Django version: 2.2.1

  • Python version: 3.6.8

  • Operating System: Ubuntu 18.04

  • Browser and version: Firefox 66.0.5 (64-bit)

  • Browser extensions/plugins you have installed: Form Filler (2.10.3) by Hussein

Description

I am trying to implement single sign-on on my django application using microsoft auth and Azure AD.
I was following the instructions on this page : https://django-microsoft-auth.readthedocs.io/en/latest/usage.html

At step 9 of "Quickstart", There is an error coming from the file /microsoft_auth/backends.py in the _verify_microsoft_user function. The function uses the email from the Azure account to create a new user, but not all azure accounts have an email and it is not possible to add one.

Environment Setup Steps

I am using localhost in debug mode
MICROSOFT_AUTH_LOGIN_TYPE = 'ma'
There is no email associated to my azure account as I don't have an Office 365 account. (screen provided)

Steps to Reproduce

Follow the instruction on this page : https://django-microsoft-auth.readthedocs.io/en/latest/usage.html
Try to log on with an Azure account with no email at step 9.
Error should occur.

Environment:Request Method: POST
Request URL: http://localhost:8000/microsoft/auth-callback/Django Version: 2.2.1
Python Version: 3.6.8
Installed Applications:
['videlio_connect',
'widget_tweaks',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'organization',
'services',
'home',
'users',
'bar',
'django.contrib.sites',
'microsoft_auth']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']Traceback:File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
 34.             response = get_response(request)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
 115.                 response = self.process_exception_by_middleware(e, request)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
 113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/django/views/generic/base.py" in view
 71.             return self.dispatch(request, *args, **kwargs)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/django/utils/decorators.py" in _wrapper
 45.         return bound_method(*args, **kwargs)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/django/views/decorators/csrf.py" in wrapped_view
 54.         return view_func(*args, **kwargs)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/microsoft_auth/views.py" in dispatch
 47.         return super().dispatch(request, *args, **kwargs)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/django/views/generic/base.py" in dispatch
 97.         return handler(request, *args, **kwargs)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/microsoft_auth/views.py" in post
 145.         context = self.get_context_data(**request.POST.dict())File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/microsoft_auth/views.py" in get_context_data
 68.         self._authenticate(kwargs.get("code"))File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/microsoft_auth/views.py" in _authenticate
 129.                 user = authenticate(self.request, code=code)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/django/contrib/auth/__init__.py" in authenticate
 73.             user = backend.authenticate(request, **credentials)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/microsoft_auth/backends.py" in authenticate
 49.                 user = self._authenticate_user()File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/microsoft_auth/backends.py" in _authenticate_user
 60.             return self._authenticate_microsoft_user()File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/microsoft_auth/backends.py" in _authenticate_microsoft_user
 74.             return self._get_user_from_microsoft(claims)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/microsoft_auth/backends.py" in _get_user_from_microsoft
 132.             user = self._verify_microsoft_user(microsoft_user, data)File "/home/nicolasabergel/Projects/env/lib/python3.6/site-packages/microsoft_auth/backends.py" in _verify_microsoft_user
 162.                 user = User.objects.get(email=data["email"])
Exception Type: KeyError at /microsoft/auth-callback/
Exception Value: 'email''

Screenshot from 2019-06-03 10-34-52

How to avoid W002 warning?

Django==2.2.3
django-microsoft-auth==2.3.0
Python 3.6.5

I think I have followed the docs but I still see

?: (microsoft_auth.W002) example.com is still a valid site, Microsoft auth might not work
HINT: Microsoft/Xbox auth uses OAuth, which requires a real redirect URI to come back to

on any manage.py operation. The authentication works. But there is still this warning. I have just one site configured:

oncall=# select * from django_site;
 id |     domain     |      name
----+----------------+----------------
  1 | localhost:8000 | mysite

and my settings.py contains SITE_ID = 1. Removing it or setting it to None makes things worse:

  File "C:\Python36\lib\site-packages\microsoft_auth\apps.py", line 39, in microsoft_auth_validator
    Site.objects.get_current(request)
  File "C:\Python36\lib\site-packages\django\contrib\sites\models.py", line 60, in get_current
    return self._get_site_by_request(request)
  File "C:\Python36\lib\site-packages\django\contrib\sites\models.py", line 35, in _get_site_by_request
    host = request.get_host()
  File "C:\Python36\lib\site-packages\django\http\request.py", line 111, in get_host
    raise DisallowedHost(msg)
django.core.exceptions.DisallowedHost: Invalid HTTP_HOST header: 'example.com'. You may need to add 'example.com' to ALLOWED_HOSTS.

And setting ALLOWED_HOSTS = ['*'] is probably not what I want to do because of security, right?

Site.objects.get_current(request) prefers SITE_ID over provided request object, so 1 is returned and Site is fetched successfully. It's not 'example.com' but the warning is still displayed. Or if I do not set SITE_ID request.get_host() fails to validate_host() and that exception is not caught in the try-catch block in microsoft_auth_validator() where only Site.DoesNotExist is expected.

Am I missing something or is there a bug?

Potential issue on RSAAlgorithm implementation

  • Django Microsoft Authentication Backend version: 2.3.1

  • Django version: 3.05

  • Python version: 3.8.2

  • Operating System: Windows 10 Version 1909

  • Browser and version: Chrome Version 81.0.4044.138

  • Browser extensions/plugins you have installed: None

Description

I tried Signing in using Microsoft auth and it fails by saying type object 'RSAAlgorithm' has no attribute 'from_jwk'
I tried looking into your source code and i found that the issue was at the client.py file. And i followed the trace and i saw that the RSAAlgorithm class does not have the attribute 'from_jwk'.
I was wondering if i missed anything?
I expected to login using this endpoint but it didn't work.

Environment Setup Steps

I have followed the steps on the documentation and i have set
MICROSOFT_AUTH_CLIENT_ID, MICROSOFT_AUTH_CLIENT_SECRET
I have modified sites configuration based on the documentation.

Steps to Reproduce

Try to login using Microsoft on the admin login page.

Capture

Infinite Redirect on Admin/

  • Django Microsoft Authentication Backend version: 1.3.0
  • Python version: 3.7
  • Django Version: 2.1.7
  • Operating System: Windows 10 Enterprise
  • Google Chrome Version 72.0.3626.121
  • Firefox Version 65.0.2
  • Chrome Extensions:
    • Ublock Origin
    • Laspass
    • Todoist
    • Grammarly

Description

I've gone through the setup detailed in your documentation but upon loading the Django admin route, Google Chrome infinitely reloads. Selecting the Microsoft or Password Login buttons have the same result. Since it redirects so often it makes it near impossible to type credentials in.

This is the only output on console log with all levels enabled:

[DOM] Input elements should have autocomplete attributes (suggested: "current-password"): (More info: https://goo.gl/9p2vKq) <input type="password" name=​"password" required id=​"id_password">​

Though I don't think it is what is causing the problem.

Firefox loads, but errors:

AADSTS50011: The reply url specified in the request does not match the reply urls configured for the application:

What I Did

Setup

Project Initialization

django-admin startproject my_project
cd my_project

Sites Configuration

Modified my_project/my_project/settings.py
Added 'django.contrib.sites' to INSTALLED_APPS

python manage.py migrate
python manage.py createsuperuser
python manage.py runserver

I then navigated to localhost:8000/admin/ to log in with my newly created user and updated the domain from example.com to localhost:8000

Microsoft App Configuration in Azure AD

Created an application in Azure AD
Added http://localhost and http://localhost:8000 to the reply URLs.
Create Secret Key in Azure AD

Configure Django for Azure AD APP

Modified my_project/my_project/settings.py
Added 'microsoft_auth' to INSTALLED_APPS
Added 'microsoft_auth.context_processors.microsoft', to TEMPLATES['OPTIONS']['context_processors']
Updated MICROSOFT_AUTH_CLIENT_ID to match Application ID in Azure AD
Updated MICROSOFT_AUTH_CLIENT_SECRET to match created Secret key in Azure AD
Updated MICROSOFT_AUTH_LOGIN_TYPE = 'ma' for Azure AD

Modified my_project/my_project/urls.py
Added path('microsoft/', include('microsoft_auth.urls', namespace='microsoft')), to urlpatterns

Lastly,

python manage.py migrate
python manage.py runserver

Output
[15/Mar/2019 09:59:03] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:03] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:03] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:04] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:04] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:04] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:04] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:04] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:04] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:04] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:04] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:04] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:04] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:05] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:05] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:05] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:05] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:05] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:05] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:05] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:05] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:05] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:05] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:05] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:05] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:06] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:06] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:06] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:06] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:06] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:06] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:06] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:06] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:06] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:06] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:07] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:07] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:07] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:07] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:07] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:07] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:07] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:07] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:07] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:07] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:08] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:08] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:08] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:08] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:08] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:08] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:08] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:08] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:09] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:09] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340
[15/Mar/2019 09:59:09] "GET /admin/ HTTP/1.1" 302 0
[15/Mar/2019 09:59:09] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 3340

Login only working in private mode of browser (for Firefox & Chrome)

Hey there! Great project and great execution! I was especially happy when I found out there you are validating the ID token you get back from Microsoft.

Still, I encountered one nasty bug when I tried to use the tool.

  • Django Microsoft Authentication Backend version: 2.3.0
  • Django version: 2.1.9
  • Python version: 3.7.1
  • Operating System: Windows 10 (Version 1903)
  • Browser and version: Firefox Developer Edition 68.0b10
  • Browser extensions/plugins you have installed: Kee, React Tools, Vue Tools, Firefox Container

Environment Setup Steps

I followed your tutorial on how to setup the things in the backend. My issue is not related to the backend, however. I run a vanilla Django 2.1.9 and configured the site etc. according to your guide.

Steps to Reproduce

Login in Firefox (+ Chrome) does not work. I tried logging into the application's backend. When I am in private mode (Firefox or Chrome) the login does work.

  1. Go to the /admin site.
  2. Click on "Microsoft".
  3. Popup Window opens. I login there.
  4. Popup Window closes. Nothing happens. (Reloading shows that I am not logged in.)

This made me investigate the frontend a little bit more. I found out that the following event listener does not catch the corresponding event (line 13 in login.js):

window.addEventListener('message', this.receiveMessage.bind(this));

When I am trying to login, this event is not fired when the window is closed. However, when I am running in private mode, it is fired. I already tried googling if this has something to do with the MessageEvent itself or if there is a know bug but I was not able to find anything.

(Also: Is this related #192?)

Thanks for the help!

Alex

Matching the redirect uri to the site name

Hi,

My django app works perfectly when I'm running this in localhost within a Docker container. However, I have pushed this same app to Azure and have matched the redirect uri in the app registration portal in the form:

https://my-app.azurewebsites.net/microsoft/auth-callback/

with the site domain name in Django Admin as:

azurewebsites.net

I get a redirect uri error when logging in. The rest of the app works fine, its just the login part.

Have you any troublshooting guidelines for this? The app is running in a Linux Docker container, so is probably behind a reverse proxy. This is a very typical setup so I'm not sure if this is the issue or not.

Have you deployed to Azure before with this functionality?

I am aware of Microsofts Authentication wrapper in Azure but its not as desirable as using your package.

Related to #141 - "Bad State"

Django Microsoft Authentication Backend version:

2.2.2

Django version:

2.2.1

Python version:

3.7.2

Operating System:

Windows 10 1809

Browser and version:

Google Chrome - 74.0.3729.169

Browser extensions/plugins you have installed:

Not related, but:

  • LastPass
  • React
  • Redux
  • JSON formatter

Description

I'm trying to authenticate via Azure AD with my Microsoft account. The authentication seems to be successful as I receive an authorization code, but the callback is where the error happens.

What I'm trying to achieve is to require all requests to be authenticated. I've made a custom middleware that does the following redirects the user to the authentication URL if request.users.is_authenticated equals False.
Note: I am able to log in with my account in the /admin site.

My custom middleware

from django.middleware.csrf import get_token
from django.shortcuts import redirect

def require_auth(get_response):
    # One-time configuration and initialization.

    def middleware(request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        if not request.user.is_authenticated:
            if request.path != '/microsoft/auth-callback/':
                state = get_token(request)
                return redirect(
                    f'https://login.microsoftonline.com/<My-tenant-id>/oauth2/v2.0/authorize?response_type=code&client_id=<My-Client-ID>&response_mode=form_post&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fmicrosoft%2Fauth-callback%2F&scope=openid+email+profile&state={state}'
                )

        response = get_response(request)

        # Code to be executed for each request/response after
        # the view is called.

        return response

    return middleware

The request:
URL: Request URL: http://localhost:8080/microsoft/auth-callback/
Method: POST
Status Code: 400 (Bad Request)
Form Data:

  • Code: My authorization code
  • State: CSRF value
  • Session State: GUID

The response/error

This window should automatically close. If it does not, it should be save to close after a few seconds.

{"microsoft_auth": {"error": "bad_state", "error_description": "An invalid state variable was provided. Please refresh the page and try again later."}}

Environment Setup Steps

My environment is set up according to the documentation.

Steps to Reproduce

  1. Set up Django Microsoft Authentication as described in the docs.
  2. Implement middleware.
  3. Navigate to any site (And you will be redirected to Microsoft's login page)
  4. Log in with your credentials.
  5. Error message

How to best carry around token for later use?

Hi, first of thanks for the nice library!

I'm using the MICROSOFT_AUTH_AUTHENTICATE_HOOK to access the auth token, but was wondering what's the cleanest/most secure way to carry it around in my application for later use ?

My use-case is that i'd like to send some emails later in a view.

Regards,
-Daniel

Able to use http instead of https for callback URI ?

Hi,

Using OAuth2Session from requests_oauthlib one can specify a redirect URI to have http as well as https and I've got this to work with my current AD setup. I've seen in the README that it says that https must be used, but I was wondering if it's possible to configure http to be used ?

Thanks,

Greg

`window.opener` is undefined in Microsoft Edge

The Microsoft Auth window does not automatically close and force the parent window to refresh after returning from Microsoft.

STR - Microsoft Edge 44.18362.1.0 on test site:

  1. Go to /admin/, you should be redirected to /admin/login/?next=/admin/
  2. Click Microsoft
  3. Log into the window that pops up. You should be redirected back to /microsoft/auth-callback/

The popped up Window should close, but it does not seem to. After doing some digging and testing, it seems to be related to window.opener not being defined.

image

This seems to be a known reported bug in Edge, though it will likely go unfixed since Edge is migrating to using Chromium instead.

https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11324352/

microsoft/auth-callback Scope Warning for v2.0

  • Django Microsoft Authentication Backend version: 2.0.0
  • Python version: 3.7.3
  • Operating System: Win 10 Pro
  • Browser and version you are testing in: Chrome v73.0.3683.103
  • What browser plugins do you have installed that may interfere with cookies or Javascript:

Description

Configured backend to authenticate to my single-tenant API on AAD, and upon reaching microsoft/auth-callback, receive long Scope warning in a popup:

Scope has changed from "profile openid email" to "DeviceManagementManagedDevices.PrivilegedOperations.All Calendars.ReadWrite.Shared User.Read.All Sites.FullControl.All MailboxSettings.ReadWrite EAS.AccessAsUser.All Policy.Read.All AccessReview.ReadWrite.All EduRoster.ReadWrite ProgramControl.ReadWrite.All Subscription.Read.All Files.ReadWrite.All Directory.ReadWrite.All DeviceManagementApps.ReadWrite.All Directory.Read.All Contacts.Read DeviceManagementManagedDevices.ReadWrite.All Mail.ReadWrite.Shared PrivilegedAccess.ReadWrite.AzureResources MailboxSettings.Read Calendars.ReadWrite Mail.ReadWrite Bookings.Manage.All identityriskyuser.read.all Policy.ReadWrite.ConditionalAccess Notes.Read DeviceManagementConfiguration.Read.All User.ReadWrite Agreement.Read.All Files.Read.All EduRoster.Read Files.ReadWrite.AppFolder Reports.Read.All Device.Read Tasks.Read Contacts.Read.Shared Notes.ReadWrite.All EduAssignments.Read Notes.Read.All IdentityProvider.Read.All AppCatalog.ReadWrite.All Calendars.Read.Shared EduAdministration.ReadWrite User.Read AccessReview.Read.All AuditLog.Read.All Bookings.Read.All BookingsAppointment.ReadWrite.All DeviceManagementConfiguration.ReadWrite.All EduAdministration.Read ProgramControl.Read.All Financials.ReadWrite.All User.Invite.All openid Device.Command Contacts.ReadWrite.Shared Directory.AccessAsUser.All People.Read People.Read.All Mail.Send EduRoster.ReadBasic DeviceManagementServiceConfig.ReadWrite.All Files.ReadWrite.Selected Notes.ReadWrite EduAssignments.ReadWriteBasic PrivilegedAccess.ReadWrite.AzureAD User.Export.All Tasks.ReadWrite.Shared DeviceManagementRBAC.ReadWrite.All Notes.Create Tasks.Read.Shared DeviceManagementRBAC.Read.All Sites.Read.All Agreement.ReadWrite.All SecurityEvents.Read.All profile Mail.Send.Shared Mail.Read.Shared User.ReadWrite.All Notes.ReadWrite.CreatedByApp AgreementAcceptance.Read.All Calendars.Read DeviceManagementApps.Read.All Files.Read Sites.ReadWrite.All DeviceManagementServiceConfig.Read.All Group.Read.All Bookings.ReadWrite.All Sites.Manage.All Member.Read.Hidden User.ReadBasic.All email EduAssignments.ReadWrite Files.Read.Selected Files.ReadWrite UserTimelineActivity.Write.CreatedByApp IdentityProvider.ReadWrite.All AgreementAcceptance.Read Tasks.ReadWrite Mail.Read Contacts.ReadWrite EduAssignments.ReadBasic Group.ReadWrite.All Notifications.ReadWrite.CreatedByApp IdentityRiskEvent.Read.All DeviceManagementManagedDevices.Read.All SecurityEvents.ReadWrite.All UserActivity.ReadWrite.CreatedByApp".

What I Did

Followed Usage guide on setting up dependencies for AAD auth.
In addition to adding MICROSOFT_AUTH_CLIENT_ID and MICROSOFT_AUTH_CLIENT_SECRET, I added MICROSOFT_AUTH_TENANT_ID to settings.py.

python manage.py runserver

also added environment variable

$env:OAUTHLIB_RELAX_TOKEN_SCOPE=$TRUE

on account of similar Scope warning issues.

Before receiving this warning, I'm pretty confident that my configuration is correct because I received several microsoft errors leading up to this. I got the "this client ID is not a multi-tenant app" error, as well as the "not a callback URI" error. After configuring my SITE_ID to use localhost, I finally got past the microsoft errors and arrived at this warning.

Traceback:


Request Method: | POST
-- | --
http://localhost:8000/microsoft/auth-callback/

2.2

Warning

Scope has changed from "email profile openid" to "People.Read Directory.AccessAsUser.All User.ReadBasic.All EduRoster.ReadBasic PrivilegedAccess.ReadWrite.AzureAD Tasks.ReadWrite DeviceManagementServiceConfig.ReadWrite.All User.Read Contacts.Read AccessReview.Read.All Calendars.ReadWrite Sites.FullControl.All Files.ReadWrite.All IdentityRiskEvent.Read.All AppCatalog.ReadWrite.All AgreementAcceptance.Read Tasks.ReadWrite.Shared DeviceManagementManagedDevices.Read.All BookingsAppointment.ReadWrite.All Tasks.Read.Shared Group.ReadWrite.All Notes.Create DeviceManagementManagedDevices.PrivilegedOperations.All DeviceManagementRBAC.ReadWrite.All IdentityProvider.ReadWrite.All DeviceManagementApps.Read.All Bookings.Manage.All AuditLog.Read.All EduAssignments.ReadWrite Notes.ReadWrite Mail.Send email Files.Read Notes.ReadWrite.CreatedByApp DeviceManagementConfiguration.ReadWrite.All Files.ReadWrite.Selected EduAssignments.Read Notes.Read.All Files.ReadWrite Mail.Send.Shared Policy.Read.All Directory.ReadWrite.All Files.ReadWrite.AppFolder EduRoster.ReadWrite Mail.Read.Shared EduAssignments.ReadBasic DeviceManagementManagedDevices.ReadWrite.All Calendars.Read.Shared ProgramControl.ReadWrite.All Contacts.ReadWrite.Shared Mail.ReadWrite People.Read.All profile EduAdministration.Read Member.Read.Hidden Group.Read.All Subscription.Read.All Contacts.ReadWrite EduAssignments.ReadWriteBasic ProgramControl.Read.All identityriskyuser.read.all Files.Read.Selected DeviceManagementConfiguration.Read.All DeviceManagementServiceConfig.Read.All Calendars.ReadWrite.Shared User.Export.All Financials.ReadWrite.All Reports.Read.All Notes.Read Device.Command Mail.Read SecurityEvents.Read.All Calendars.Read Sites.Read.All PrivilegedAccess.ReadWrite.AzureResources IdentityProvider.Read.All Agreement.Read.All SecurityEvents.ReadWrite.All Notifications.ReadWrite.CreatedByApp Mail.ReadWrite.Shared User.ReadWrite Files.Read.All Sites.Manage.All Bookings.Read.All Policy.ReadWrite.ConditionalAccess Sites.ReadWrite.All EduRoster.Read UserActivity.ReadWrite.CreatedByApp openid EduAdministration.ReadWrite AccessReview.ReadWrite.All UserTimelineActivity.Write.CreatedByApp User.Read.All User.ReadWrite.All AgreementAcceptance.Read.All Notes.ReadWrite.All DeviceManagementRBAC.Read.All Agreement.ReadWrite.All DeviceManagementApps.ReadWrite.All MailboxSettings.Read User.Invite.All Contacts.Read.Shared Directory.Read.All EAS.AccessAsUser.All Bookings.ReadWrite.All MailboxSettings.ReadWrite Device.Read Tasks.Read".


3.7.3

pipenv install failure (docker)

  • Django Microsoft Authentication Backend version: 2.3.1
  • Django version: 3.0.2
  • Python version: 3.8
  • Operating System: python:3.8.0-alpine (docker)
  • Browser and version: Firefox 75 (x64)
  • Browser extensions/plugins you have installed: N/A

Description

What happened

I have a docker image that pulls python:3.8.0-alpine. In the Dockerfile, I'm installing py3-cffi and py3-cryptography. When attempting to install using pipenv, the installation fails.

What went wrong

When I initiate the install using docker-compose exec web pipenv install django_microsoft_auth==2.3.1, I receive the stacktrace:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pipenv/resolver.py", line 126, in <module>
    main()
  File "/usr/local/lib/python3.8/site-packages/pipenv/resolver.py", line 119, in main
    parsed.requirements_dir, parsed.packages)
  File "/usr/local/lib/python3.8/site-packages/pipenv/resolver.py", line 85, in _main
    requirements_dir=requirements_dir,
  File "/usr/local/lib/python3.8/site-packages/pipenv/resolver.py", line 69, in resolve
    req_dir=requirements_dir
  File "/usr/local/lib/python3.8/site-packages/pipenv/utils.py", line 726, in resolve_deps
    req_dir=req_dir,
  File "/usr/local/lib/python3.8/site-packages/pipenv/utils.py", line 480, in actually_resolve_deps
    resolved_tree = resolver.resolve()
  File "/usr/local/lib/python3.8/site-packages/pipenv/utils.py", line 385, in resolve
    results = self.resolver.resolve(max_rounds=environments.PIPENV_MAX_ROUNDS)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/resolver.py", line 102, in resolve
    has_changed, best_matches = self._resolve_one_round()
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/resolver.py", line 206, in _resolve_one_round
    for dep in self._iter_dependencies(best_match):
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/resolver.py", line 301, in _iter_dependencies
    dependencies = self.repository.get_dependencies(ireq)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/repositories/pypi.py", line 234, in get_dependencies
    legacy_results = self.get_legacy_dependencies(ireq)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/repositories/pypi.py", line 426, in get_legacy_dependencies
    results, ireq = self.resolve_reqs(download_dir, ireq, wheel_cache)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/repositories/pypi.py", line 297, in resolve_reqs
    results = resolver._resolve_one(reqset, ireq)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/resolve.py", line 260, in _resolve_one
    abstract_dist = self._get_abstract_dist_for(req_to_install)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/resolve.py", line 213, in _get_abstract_dist_for
    self.require_hashes
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/operations/prepare.py", line 294, in prepare_linked_requirement
    abstract_dist.prep_for_dist(finder, self.build_isolation)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/operations/prepare.py", line 127, in prep_for_dist
    self.req.run_egg_info()
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/req/req_install.py", line 474, in run_egg_info
    command_desc='python setup.py egg_info')
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/utils/misc.py", line 705, in call_subprocess
    % (command_desc, proc.returncode, cwd))
pipenv.patched.notpip._internal.exceptions.InstallationError: Command "python setup.py egg_info" failed with error code 1 in /tmp/tmpda8ehjv5build/django-microsoft-auth/
File "/usr/local/lib/python3.8/site-packages/pipenv/resolver.py", line 126, in <module>
    main()
  File "/usr/local/lib/python3.8/site-packages/pipenv/resolver.py", line 119, in main
    parsed.requirements_dir, parsed.packages)
  File "/usr/local/lib/python3.8/site-packages/pipenv/resolver.py", line 85, in _main
    requirements_dir=requirements_dir,
  File "/usr/local/lib/python3.8/site-packages/pipenv/resolver.py", line 69, in resolve
    req_dir=requirements_dir
  File "/usr/local/lib/python3.8/site-packages/pipenv/utils.py", line 726, in resolve_deps
    req_dir=req_dir,
  File "/usr/local/lib/python3.8/site-packages/pipenv/utils.py", line 480, in actually_resolve_deps
    resolved_tree = resolver.resolve()
  File "/usr/local/lib/python3.8/site-packages/pipenv/utils.py", line 385, in resolve
    results = self.resolver.resolve(max_rounds=environments.PIPENV_MAX_ROUNDS)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/resolver.py", line 102, in resolve
    has_changed, best_matches = self._resolve_one_round()
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/resolver.py", line 206, in _resolve_one_round
    for dep in self._iter_dependencies(best_match):
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/resolver.py", line 301, in _iter_dependencies
    dependencies = self.repository.get_dependencies(ireq)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/repositories/pypi.py", line 234, in get_dependencies
    legacy_results = self.get_legacy_dependencies(ireq)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/repositories/pypi.py", line 426, in get_legacy_dependencies
    results, ireq = self.resolve_reqs(download_dir, ireq, wheel_cache)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/piptools/repositories/pypi.py", line 297, in resolve_reqs
    results = resolver._resolve_one(reqset, ireq)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/resolve.py", line 260, in _resolve_one
    abstract_dist = self._get_abstract_dist_for(req_to_install)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/resolve.py", line 213, in _get_abstract_dist_for
    self.require_hashes
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/operations/prepare.py", line 294, in prepare_linked_requirement
    abstract_dist.prep_for_dist(finder, self.build_isolation)
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/operations/prepare.py", line 127, in prep_for_dist
    self.req.run_egg_info()
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/req/req_install.py", line 474, in run_egg_info
    command_desc='python setup.py egg_info')
  File "/usr/local/lib/python3.8/site-packages/pipenv/patched/notpip/_internal/utils/misc.py", line 705, in call_subprocess
    % (command_desc, proc.returncode, cwd))
pipenv.patched.notpip._internal.exceptions.InstallationError: Command "python setup.py egg_info" failed with error code 1 in /tmp/tmpda8ehjv5build/django-microsoft-auth/

What did I expect to happen

Successul install of django_microsoft_auth.

Environment Setup Steps

This is not yet a production application. I am working on this on my localhost.

Here is my directory structure:

├── app
│   ├── config
│   │   └── settings.py
│   └── Dockerfile
├── docker-compose.yml
└── .env.dev

docker-compose.yml:

version: '3.7'

services:
  web:
    build: ./app
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - ./app/:/usr/src/app/
    ports:
      - 8000:8000
    env_file:
      - ./.env.dev
    depends_on:
      - db
  db:
    image: postgres:12.0-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=secretpassword
      - POSTGRES_DB=postgres

volumes:
  postgres_data:

Dockerfile:

# pull official base image
FROM python:3.8.0-alpine

# set work directory
WORKDIR /usr/src/app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install psycopg2 dependencies
RUN apk update \
    && apk add postgresql-dev \
       gcc \
       python3-dev \
       musl-dev \
       jpeg-dev \
       zlib-dev \
       py3-cffi \
       py3-cryptography

# install dependencies
RUN pip install --upgrade pip
COPY ./Pipfile /usr/src/app/Pipfile
COPY ./Pipfile.lock /usr/src/app/Pipfile.lock
RUN pip install pipenv && pipenv install --system

# copy entrypoint.sh
COPY ./entrypoint.sh /usr/src/app/entrypoint.sh

# copy project
COPY . /usr/src/app/

# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]

Steps to Reproduce

docker-compose exec web pipenv install django_microsoft_auth==2.3.1

Any help would be greatly appreciated!

TypeError at /microsoft/auth-callback/ Expecting a PEM- or RSA-formatted key.

  • Django Microsoft Authentication Backend version:2.2.2
  • Python version: 3.7
  • Operating System: Windows
  • Browser and version you are testing in: chrome
  • What browser plugins do you have installed that may interfere with cookies or Javascript:

Description

I receive this error
Internal Server Error: /microsoft/auth-callback/
TypeError at /microsoft/auth-callback/ Expecting a PEM- or RSA-formatted key.

What I Did

Access on admin site

Two users found during authentication, then exception

  • Django Microsoft Authentication Backend version: django-microsoft-auth==1.1.1
  • Django: Django==2.0.5
  • Python version: Python 3.6.7
  • Operating System: AWS AMI Linux; Docker container: FROM python:3.6

Description

Trying to login with my email authenticating against Office365
Other domain users worked properly; first login fails, then I give them rights and then everything works
When I tried to login with my email account I got an error

What I Did

When I type my email address I am asked to choose between my personal account and work account (both share the same email address, different passwords, different Microsoft user backend database).

I choose work account.
After type the password I got an Exception:

MultipleObjectsReturned at /microsoft/auth-callback/
get() returned more than one User -- it returned 2!
Request Method: | POST
Request URL: http://domain.com/microsoft/auth-callback/
Django Version: 2.0.5
Exception Type: MultipleObjectsReturned
Exception Value: get() returned more than one User -- it returned 2!
Exception Location: /usr/local/lib/python3.6/site-packages/django/db/models/query.py in get, line 407
Python Executable: /usr/local/bin/python
Python Version: 3.6.7
Python Path: ['/app', '/usr/local/lib/python36.zip', '/usr/local/lib/python3.6', '/usr/local/lib/python3.6/lib-dynload', '/usr/local/lib/python3.6/site-packages']
Server time: Fri, 9 Nov 2018 12:40:25 +0000

Do not know how to proceed

Case Insensitive Email User Retrieval

Hi !

My problem is that if a user already exist in the database with the same email
but in different case, Django Microsoft Auth won't find him.

This is because in the file backend.py, line 162, we retrieve the User like this:
user = User.objects.get(email=data["email"])
Instead of like this (case insensitive):
user = User.objects.get(email__iexact=data["email"])

  • Django Microsoft Authentication Backend version: 2.3.1
  • Django version: 2.2.6
  • Python version: 3.6.8
  • Operating System: Windows 10
  • Browser and version: Firefox 70

Step to reproduce:

microsoft/auth-callback Scope warning during POST.

Django Microsoft Authentication Backend version: 1.3.0
Python version: 3.7
Django Version: 2.1.7
Operating System: Windows 10 Enterprise
Google Chrome Version 72.0.3626.121
Chrome Extensions:

  • Ublock Origin
  • Laspass
  • Todoist

Description

I've gone through the setup detailed in your documentation and am able to go through all of the authentication steps up until what I think is the hand-off from Microsoft to the admin panel.

What I Did

Setup
Project Initialization

django-admin startproject my_project
cd my_project
Sites Configuration

Modified my_project/my_project/settings.py
Added 'django.contrib.sites' to INSTALLED_APPS

python manage.py migrate
python manage.py createsuperuser
python manage.py runserver

I then navigated to localhost:8000/admin/ to log in with my newly created user and updated the domain from example.com to localhost:8000

Microsoft App Configuration in Azure AD

Created an application in Azure AD
Added Reply-URLs

Create Secret Key in Azure AD
Configure Django for Azure AD APP

Modified my_project/my_project/settings.py
Added 'microsoft_auth' to INSTALLED_APPS
Added 'microsoft_auth.context_processors.microsoft', to TEMPLATES['OPTIONS']['context_processors']
Updated MICROSOFT_AUTH_CLIENT_ID to match Application ID in Azure AD
Updated MICROSOFT_AUTH_CLIENT_SECRET to match created Secret key in Azure AD
Updated MICROSOFT_AUTH_LOGIN_TYPE = 'ma' for Azure AD

Modified my_project/my_project/urls.py
Added path('microsoft/', include('microsoft_auth.urls', namespace='microsoft')), to urlpatterns

Lastly,

python manage.py migrate
python manage.py runserver

The Exception

After authentication on through microsoft, I recieve the following Warning from Django:

Warning at /microsoft/auth-callback/
Scope has changed from "User.Read" to "User.Read email profile openid".

Key Value
Request Method POST
Request http://localhost:8000/microsoft/auth-callback/
Django Version 2.1.7
Exception Type Warning
Exception Value Scope has changed from "User.Read" to "User.Read email profile openid".
Exception Location C:\ProgramData\Anaconda3\lib\site-packages\oauthlib\oauth2\rfc6749\parameters.py in validate_token_parameters, line 455

After searching on the web for a bit I found that for some, updating the scope from "User.Read" to "User.Read profile email openid", but I don't think that is something currently modifiable in this project.

Running server

I am using following command run server.
python -m tests.site runserver 0:8001

But I am getting an error as follows.
ModuleNotFoundError: No module named 'tests'

Login with Microsoft Office365 is getting failed.

  • Django Microsoft Authentication Backend version:
  • Python version: 3.5
  • Operating System: Ubuntu 16.04

Description

Login with Microsoft Office365 is getting failed. It din't created user in django admin unlike its mentioned in tutorial as it should create. I can only see two accounts(Microsoft accounts and Microsoft xbox-live accounts but not Microsoft office 365 accounts)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.