You are browsing a read-only backup copy of Wikitech. The primary site can be found at wikitech.wikimedia.org

Help:Tool Labs/My first Django OAuth tool

From Wikitech-static
< Help:Tool Labs
Revision as of 21:13, 25 February 2017 by imported>Tobias47n9e (add information about callback URL)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

This guide will show how to set up a Django app on wmflabs. We will use python-social-auth to implement OAuth authentification with Wikipedia, using the Mediawiki OAuth capabilities.

If you are new to Django you should read through some of the tutorials in the Tutorials section first.


Local development and testing

Create your Django project

This step is not different from the many tutorials that you can find for Django.

It is recommended to create a Python 3 virtual environment:

$ python3 -m venv venv-my-first-django-oauth-app
$ source venv-my-first-django-oauth-app/bin/activate
$ pip install django

Then set up a new Django project:

$ mkdir my-first-django-oauth-app
$ cd my-first-django-oauth-app
$ mkdir src
$ django-admin startproject oauth_app src

Now we have the main app set up and the project folder structure will look like this:

[my-first-django-oauth-app]$ tree
.
└── src
    ├── manage.py
    └── oauth_app
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py

Next we need to add an app for for our actual webpage:

$ cd src
$ django-admin startapp user_profile

The structure will then look like this:

[my-first-django-oauth-app]$ tree
.
└── src
    ├── manage.py
    ├── oauth_app
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── user_profile
        ├── admin.py
        ├── apps.py
        ├── __init__.py
        ├── migrations
        │   └── __init__.py
        ├── models.py
        ├── tests.py
        └── views.py

Then add this new app to the installed app in settings.py:

INSTALLED_APPS = [
    ...
    'user_profile',
]

And then route the main page from the main app to our new user_profile app. In urls.py in the main app add:

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'', include('user_profile.urls')),
]

Create a urls.py in your user_profile as as well, and add the following to it:

from django.conf.urls import url
from user_profile import views

urlpatterns = [
    url(r'', views.index),
]

The index view is still missing. Create it in views.py:

from django.shortcuts import render

def index(request):
    context = {}
    return render(request, 'user_profile/index.dtl', context)

Now we only need to create the Django template in the folder templates/user_profile/index.dtl

<!DOCTYPE html>
<html>
<body>
  <h1>My first Django OAuth app</h1>
</body>
</html>

The current file structure will look something like this:

[my-first-django-oauth-app]$ tree
.
└── src
    ├── db.sqlite3
    ├── manage.py
    ├── oauth_app
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── user_profile
        ├── admin.py
        ├── apps.py
        ├── __init__.py
        ├── migrations
        │   └── __init__.py
        ├── models.py
        ├── templates
        │   └── user_profile
        │       └── index.dtl
        ├── tests.py
        ├── urls.py
        └── views.py

Now you can start Django's built in development webserver:

$ python manage.py runserver

This will show you the template you just created.

Adding OAuth

Starting with version 1.2 the Python package

social-core

has a Mediawiki backend that works for any of Wikimedia Foundations wikis, but also for any other Mediawiki installation that has the OAuth Extension enabled.

Install the package for your virtual environment:

$ pip install social-auth-app-django

Add the following in your main app's settings.py:

INSTALLED_APPS = [
    ...
    'social_django',
]

MIDDLEWARE_CLASSES = [
    ...
    'social_django.middleware.SocialAuthExceptionMiddleware',
]

TEMPLATES = [
    {
        ...
        'OPTIONS': {
            'context_processors': [
                ...
                'social_django.context_processors.backends',
                'social_django.context_processors.login_redirect',
            ],
        },
    },
]

AUTHENTICATION_BACKENDS = (
    'social_core.backends.mediawiki.MediaWiki',
    'django.contrib.auth.backends.ModelBackend',
)

Then we need to add settings for the OAuth provider. You can register your application, after reading the documentation here (OAuth for developers.

We will register a consumer for develpment at this moment, so we will use the following settings:

Application name: use a name that indicates that you are develping locally
Contact email address: Use a valid email where you can be reached.
Applicable project: All is fine
OAuth "callback" URL: http://127.0.0.1:8000/
Select: Allow consumer to specify a callback in requests and use "callback" URL above as a required prefix.
Types of grants being requested: Choose "User identity verification only, no ability to read pages or act on a user's behalf."
Public RSA key: You can leave this empty at the moment.

Be sure not to commit these keys in version control and keep them secret.

SOCIAL_AUTH_MEDIAWIKI_KEY = '**super secret key**'
SOCIAL_AUTH_MEDIAWIKI_SECRET = '**super secret secret**'
SOCIAL_AUTH_MEDIAWIKI_URL = 'https://meta.wikimedia.org/w/index.php'
SOCIAL_AUTH_MEDIAWIKI_CALLBACK = 'http://127.0.0.1:8000/oauth/complete/mediawiki/'

After that you need to apply the migrations in order to create the user models in the database.

$ python manage.py migrate

Next we need to up a few things for the profile view and the login. Update your user_profile apps urls.py to say something like this:

from django.conf.urls import url, include
from user_profile import views

urlpatterns = [
    url(r'profile', views.profile, name='profile'),
    url(r'^accounts/login', views.login_oauth, name='login'),
    url(r'^oauth/', include('social_django.urls', namespace='social')),
    url(r'', views.index),
]

Create two new views for the profile and the login:

from django.shortcuts import render
from django.contrib.auth.decorators import login_required


def index(request):
    context = {}
    return render(request, 'user_profile/index.dtl', context)

@login_required()
def profile(request):
    context = {}
    return render(request, 'user_profile/profile.dtl', context)

def login_oauth(request):
    context = {}
    return render(request, 'user_profile/login.dtl', context)

Then create the login.dtl file:

<!DOCTYPE html>
<html>
<body>
  <h1>Login</h1>
  <a href="{% url 'social:begin' 'mediawiki' %}">Login with Wikimedia</a>
</body>
</html>

And the profile.dtl file:

<!DOCTYPE html>
<html>
<body>
  <h1>Profile</h1>
  {{ user }}
</body>
</html>

And finally update your index.dtl to say:

<!DOCTYPE html>
<html>
<body>
  <h1>My first Django OAuth app</h1>
  <a href="{% url 'profile' %}">Profile</a>
</body>
</html>

When you now restart the server and click on the "Profile" link you will be asked to give permission to your newly created OAuth consumer. After approving the consumer you will be redirected to the user page which will print the Wikimedia user name.

Deploying to wmflabs

>>> Coming soon!

Links

Tutorials

Further Reading

Other tools