Part VIII – User Authentication with a Google Account using Django Allauth

In this part of the tutorial, we’re going to manage user authentication using the django-allauth package, which let’s you configure quite a few Social Accounts, including Facebook, Twitter or Google.

The idea is that when a user visits the home page, it can log in (or register) using any of the available social account services. Moreover, the database creates a new User instance every time a user is registered through this process.

In this part we’re going to focus on Google authentication, and as always, we’re going to start writing a test 🙂

Django authorized by GoogleThe outline of this part is:

 

Define what we expect and write a Test

As we haven’t touched the base.html template that came with HTML5 Boilerplate, when we go to the TaskBuster home page we see a top navigation bar with a Sign in form.

login-bar

We are going to modify it so that only contains a button that says “Sign in with Google”, visible for users that are not logged in, and a “Logout” button for the others.

Let’s write a new functional test in functional_tests/test_allauth.py (you have to create this file):

The previous test:

  • Initializes a browser in setUp. WebDriverWait is used to make the browser wait a certain amount of time before rising an exception when an element is not found.
  • tearDown just quits the browser
  • get_element_by_id and get_button_by_id are helper functions that use WebDriverWait to find elements by ID. Note that for a button we wait until the element is clickable.
  • get_full_url is another helper function that we used in other tests. It returns the full url given a reverse name.
  • test_google_login is the main test here. It goes to the home page and:
    • checks that the login button is present
    • checks that the logout button is not present
    • checks that the login button points to the correct url (/accounts/google/login)
    • checks that after clicking on the login button, the user gets logged in and it sees the logout button instead.
    • a click on the logout button should make the user see the login button again.

Now that we know what we want, let’s install the allauth package 🙂

Install django-allauth

Let’s install the package django-allauth, which allows users to register and log in using different social accounts like Google or Twitter.

which will install several libraries:

You should add them all into the requirements/base.txt file, and install them into the testing environment.

Note: if the version of django-allauth < 0.20.0, you should install the development version in order to be compatible with Django 1.8, with:

Settings File

Next, open the settings/base.py file and make sure you have the django.template.context_procesors.request. If you’re using Django 1.7, you’ll have to use allauth context processors (read more):

Next, we need to include the Authentication Backend used by allauth:

And the required apps (including the app for Google):

Note that we are adding these Installed Apps into the existing INSTALLED_APPS  setting using +=.

The SITE_ID parameter is used by the Django sites framework.

Finally, we are going to set the following parameters to customize the authorization process:

This will make allauth to ask for the email (if possible) in the authorization process. It will ask it to Google, without any verification process, and after logging in, it will redirect the user to the home page.

You can find more info about the available settings here.

Urls

Next open the taskbuster/urls.py file and add the corresponding urls before the i18n internationalization urls:

Database migrations

Ok, now we just need to update the database:

Sites configuration

Next, we need to configure the Sites Framework. Run the development server with

and go to the admin interface at http://127.0.0.1:8000/admin/sites/site and create a Site for the localhost, 127.0.0.1:8000, or your website domain for production. If you have an example.com site defined, modify it so it has an id equal to the SITE_ID=1 setting variable. Otherwise, if you create a new site, you have to change the settings variable, SITE_ID, with the ID of the site you just created (probably 2).

Note: you need to create a superuser account to access the Django admin. If you don’t have it yet, you can create a new one with:

We are ready to create our Google Application!

Goolge App Registration

First, we are going to create a Google App to obtain a key/secret pair. Go to the Google Developers Console and click on Create Project. Choose a name for your project and an ID.

Next, click on your newly created project and on the left menu select APIs & auth –> Credentials and click on the Consent screen tab. You should provide at least a Name and an Email.

Go back to the Credentials tab and click on Create new Client ID. Select Web Application and use:

Note that the redirect URI proposed automatically is different from the one written here 🙂

This app will work in our development and testing environment. You should create another Client/secret pair for production, and change http://127.0.0.1:8000/ by your website domain.

Great! We have our Google App ready, so let’s configure the Django part!

Allauth Django Configuration

Create a Social Application for Google at http://127.0.0.1:8000/admin/socialaccount/socialapp, with the following properties:

  • Provider: Google
  • Name: Google (or something similar)
  • Client ID: your application Client ID (obtained in the Developers Console at APIs & auth –> Credentials).
  • Secret Key: your application Client Secret
  • Key: not needed (leave blank).
  • Select the corresponding site.

Finally, just save the instance.

Testing the user flow

Ok, now we are ready to run our tests!

First, it fails because the home page doesn’t have an element with an id equal to google_login.

Let’s edit the taskbuster/templates/base.html file and find the navigation bar. There you should replace the form tag by the following code:

We have included some logic here, to display the Sign in button only when the user is not logged in, and the logout button otherwise.

If you run the tests again, you’ll see that we get an Internal Error after clicking on the Sign in button. This is because the testing database doesn’t have a Google App defined (the testing database is empty!). Let’s change this!

As in the development database we only have a Site, a Google App and the admin user, we are going to use it to dump its data to create a fixture.

First, create the folder fixutres:

and next, create the fixture with

Open you .gitignore file and add a line to omit this folder, as it contains sensitive information

Next, we need to load this fixture in our tests. In your settings/testing.py file indicate the fixture folder

and at the beginning of your test class, include the fixture as

Ok, try again to run your tests.

This time you’ll see the Google Authorization page, where the user should indicate its username and password to log in, and the test fails as it can’t find the logout button.

Let’s make the test to insert our credentials. Create the file taskbuster/fixtures/google_user.json and write

where you should insert a valid Google Credentials. As this file is located under the fixtures folder, it won’t be in the git repository.

Note that the keys Email and Passwd are the html element ids of the Google login form.

Next, add the following method inside the test, that will be called after clicking on the Sign in button:

Ok, if you run this test again you’ll see the following message in the browser:

test_redirect_uri

indicating that the redirect URI at http://localhost:8081 is not valid. This is because we registered a different url, http://127.0.0.1:8000, and not the one that is used by tests.

Go back into the Developers Console and register the url http://localhost:8081 and the corresponding callback url in your app.

Next, open the taskbuster/fixtures/allauth_fixture.json, and replace all occurrences of 127.0.0.1:8000 for localhost:8081 (I counted 3).

Run the test again.

Yes! the authorization process was successful 🙂

But… when the Logout button is clicked, you are redirected to another url, with a confirmation form in it.

In order to omit this step, edit the taskbuster/urls.py file and add the following line before including allauth.urls:

This will make the user to go back to the home page after clicking the Logout button.

Ok, run your tests again, this time it should work! 🙂

Well Done!!

Can you try to configure another Social Account? Like Twitter, LinkedIn or Facebook?

What’s next?

Now, you can:

Please, +1 and share if useful! Thanks! 🙂

Google+TwitterLinkedInFacebookReddit

Please, add +Marina Mele in your comments. This way I will get a notification email and I will answer you as soon as possible! :-)