Git Product home page Git Product logo

django-nopassword's Introduction

django-nopassword

CircleCI

Authentication backend for django that uses a one time code instead of passwords.

This project was originally inspired by Is it time for password-less login? by Ben Brown

Installation

Run this command to install django-nopassword

pip install django-nopassword

Requirements

Django >= 1.11 (custom user is supported)

Usage

Add the app to installed apps

INSTALLED_APPS = (
    ...
    'nopassword',
    ...
)

Add the authentication backend EmailBackend

AUTHENTICATION_BACKENDS = (
    # Needed to login by username in Django admin, regardless of `nopassword`
    'django.contrib.auth.backends.ModelBackend',

    # Send login codes via email
    'nopassword.backends.email.EmailBackend',
)

Add urls to your urls.py

urlpatterns = patterns('',
    ...
    url(r'^accounts/', include('nopassword.urls')),
    ...
)

REST API

To use the REST API, djangorestframework must be installed

pip install djangorestframework

Add rest framework to installed apps

INSTALLED_APPS = (
    ...
    'rest_framework',
    'rest_framework.authtoken',
    'nopassword',
    ...
)

Add TokenAuthentication to default authentication classes

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    )
}

Add urls to your urls.py

urlpatterns = patterns('',
    ...
    url(r'^api/accounts/', include('nopassword.rest.urls')),
    ...
)

You will have the following endpoints available:

  • /api/accounts/login/ (POST)
    • username
    • next (optional, will be returned in /api/accounts/login/code/ to be handled by the frontend)
    • Sends a login code to the user
  • /api/accounts/login/code/ (POST)
    • code
    • Returns key (authentication token) and next (provided by /api/accounts/login/)
  • /api/accounts/logout/ (POST)
    • Performs logout

Settings

Information about the available settings can be found in the docs

Tests

Run with python setup.py test.


MIT © Rolf Erik Lekang

django-nopassword's People

Contributors

akoumjian avatar alej0varas avatar ataylor32 avatar codingjoe avatar daronstinnett avatar grumps avatar gthomas avatar jbeyers avatar jpadilla avatar mjumbewu avatar relekang avatar requires avatar rubengrill avatar smajda avatar yonilavi 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

django-nopassword's Issues

User lookup in third party systems

Make it possible to call backend.is_legit_user() or something like that. The method should check if the email, phone number etc. is in another system.

user creation on signup

@relekang Do i need to create the users separately? Currently it raises DoesNotExist here. I am just visiting the /accounts/login/ and it is presenting me a input field with submit button. Upon entering the username in the field i get exception as mentioned above.

Authenticate() Returns Fails: Exception Value: Cannot resolve keyword 'code' into field.

I'm having a bit of an issue when attempting to login using the token via
Request URL: http://127.0.0.1:8000/accounts/login-code/fHZw1GJuNSgb8D5ZaafX/?next=/

I get the following error:

Exception Value: Cannot resolve keyword 'code' into field. Choices are: comment_comments, comment_flags, date_joined, email, first_name, groups, id, is_active, is_staff, is_superuser, last_login, last_name, logentry, login_codes, password, primaryguest, ratings, sitepermissions, user_permissions, username

I do have the AUTH_PROFILE_MODULE set for my custom User model.

Do I need to set AUTH_USER_MODEL to the django-nopassword model? Would this break other authentication methods?

full trace:http://pastebin.com/jYC2Cbi5

EmailBackend needs 'supports_inactive_user'

DeprecationWarning: Authentication backends without a supports_inactive_user attribute are deprecated. Please define it in django_nopassword.backends.EmailBackend. DeprecationWarning)

User Agent Detection

I've used this package on several sites now and have run into two different, related problems:

First, I built an internal business application that ran into problems because the company's internal firewall was making a GET request to the login code URLs before passing it along to the user's browser, resulting in a 404 because the firewall's request invalidated the login code. This is, of course, exceptionally annoying IT behavior, but my workaround was to customize the login view to detect their firewall's IP and simply return a 200 to it.

Second, I recently found (and blogged about) an issue where applications that use Facebook App Links can cause Facebook to make a GET request to any URL clicked in the application, also invalidating the login code. This is, of course, also exceptionally annoying behavior, and my workaround was to use the user-agents package to return a HttpResponseForbidden to invalid user agents. Here's my modified login_with_code:

def login_with_code(request, login_code):
    ua = user_agents.parse(request.META.get('HTTP_USER_AGENT') or '')
    if not (ua.is_pc or ua.is_mobile or ua.is_tablet):
        return HttpResponseForbidden()
    code = get_object_or_404(LoginCode.objects.select_related('user'), code=login_code)
    return login_with_code_and_username(request, username=get_username(code.user),
                                    login_code=login_code)

I don't know if there's anything that could be done within django-nopassword to handle these situations better. It seems heavy-handed to require user-agents as a dependency (along with it's dependencies, as it uses ua-parser), but the alternative would be to bundle some basic user agent detection into django-nopassword, which seems outside of the scope. On the other: this could effect a lot of people using this package so maybe it's worth it?

Likewise, the first situation above, that of the evil corporate firewall, could be solved by possibly adding a ip address blacklist setting. On the other hand, that also could be seen as outside the scope of this package.

Maybe the solution is just documentation explaining how to work around each of these scenarios?

What do you think? This has affected me on multiple occasions so I'm happy to help out with some solution, but I'm not sure what the best solution would be.

django-nopassword-2.1.0 PIP package installing files outside of nopassword directory

It appears the pip package is leaking files into the tests modules directory, I think they should be nopassword/tests? Please see the snipped output below from "pip uninstall django-nopassword":

Uninstalling django-nopassword-2.1.0
[SNIP]
This file was in the right place
/home/rpm/python/lib/python2.7/site-packages/nopassword/views.py

The ones below are suspect:
/home/rpm/python/lib/python2.7/site-packages/tests/init.py
/home/rpm/python/lib/python2.7/site-packages/tests/models.py
/home/rpm/python/lib/python2.7/site-packages/tests/settings.py
/home/rpm/python/lib/python2.7/site-packages/tests/test_backends.py
/home/rpm/python/lib/python2.7/site-packages/tests/test_models.py
/home/rpm/python/lib/python2.7/site-packages/tests/test_views.py
/home/rpm/python/lib/python2.7/site-packages/tests/tests.py
/home/rpm/python/lib/python2.7/site-packages/tests/urls.py

tag new release supporting Django 2.0+?

It looks like Django 2.0 support was added in the last 6 months, but there hasn't been a new release that includes these changes. Would it be possible to release a new version to pypi with these updates?

Thank you for building a package that helps get rid of passwords!

Some directories are not included when installing with pip

On the left you can see the directories tree from the github. On the right is my lib directory with the package after the installation. Two directories don't exist on my side. "Rest" is the one that I need and is not here. I did install djangorestframework but the problem persists.
restmissing

When I clone/download and use the package as an app it works. But using pip install django-nopassword fails in installing all directories.

Any suggestion? Is it a bug from your side or it was just me that does something wrong? I over checked this several times and I am clueless. I spotted a similar issue (#6) with templates: #6

Thank you

base backend needs request as first positional argument from django 1.11

From Django 1.11, auth backends need to have request as the first positional argument to the authenticate method. The current implementation of nopassword is supposed to still work, if you look at the commit here:

django/django@c31e7ab

But it does not. Rather than messing around with their deprecation logic, I just added the arg to nopassword, and it authenticates.

PR to follow shortly.

Note that the PR is quick and dirty:

  1. It's tested in my instance of Django 1.11, but NOT in previous versions, so I'm not sure it's backwards compatible.
  2. It might make sense to pass the request all the way through from the login method. Not needed in my case.

Make it possible to use without twilio

Since TwilioBackend is imported in nopassword/backends/__init__.py. It will crash without the twilio package.

Possible solution in nopassword/backends/__init__.py:

# -*- coding: utf-8 -*-
from .email import EmailBackend
try:
    from .sms import TwilioBackend
except ImportError:
    pass # twilio package not installed

Improve customization for forms

It is very hard to use a custom form, especially when using REST:

  1. Create a custom form
  2. Create a custom serializer using that form
  3. Create a custom view using that serializer
  4. Don't use include to include all nopassword urls, but instead include all urls seperately just to be able to use the new view

It would be great if we would support dynamic loading of the used form classes, in the same way as django rest auth is doing it:
https://github.com/Tivix/django-rest-auth/blob/master/rest_auth/app_settings.py#L28

They have a setting REST_AUTH_SERIALIZERS where custom serializer class names can be specified , and those serializers are loaded dynamically.
We could provide some similar setting NOPASSWORD_FORMS, those forms would be used both by the regular views and by the serializers.
This way providing a custom form + changing settings would be enough to integrate custom forms.

Support for Signup

It would be great to also have a signup integrated to have a complete authentication process.
As an example, django rest auth has an optional module rest_auth.registration to have a signup additional to login/logout/pw reset/pw change:
https://github.com/Tivix/django-rest-auth/tree/master/rest_auth/registration

The registration has built in support for allauth email verification.

There are some questions regarding this:

  1. Does signup need to be optional or should signup always be included (in urls.py). In django rest auth, I think they made it optional because for rest_auth the dependency to allauth is optional whereas for rest_auth.registration it is not.
  2. Does signup need email verification? When using the email backend, after logging in the email is indirectly verified by having access to the login code.
  3. Should a login code be contained in the signup email, or should a user just do the regular login process afterwards?

Move to jazzband

I don't use this package myself anymore, I would like to transfer it to jazzband to try to make the future a bit brighter for those of you who do.

  • Set up CI according to jazzband docs

REST login_url for external frontend

In #79 the LoginForm.save() accepts a parameter login_code_url with a default value of login_code_url, that will be used for reversing a url for the link in the email.

This means that a vendor either has to include both urls, or to provide a custom view just to have a matching url:

# include both urls, to handle the `login_code` server side, not via frontend
path('accounts/', include('nopassword.urls')),
path('api/accounts/', include('nopassword.rest.urls')),

# custom view, the url matches the url routing in the frontend application
path('accounts/login/code/', TemplateView.as_view(template_name='index.html'), name='login_code'),
path('api/accounts/', include('nopassword.rest.urls')),

It would be better if the vendor doesn't have to provide a custom view or to include both regular + rest views.
Maybe we should introduce some setting NOPASSWORD_LOGIN_CODE_URL, similar to django default setting LOGIN_URL, it could also be a url name or an actual url (anything that resolve supports).
This way, we would also support that the api and frontend are running on different machines, and the NOPASSWORD_LOGIN_CODE_URL would point to a url on a different server.

Code Sender Backends

Hey @relekang great work on this. I really want to contribute some more and I think a useful enhancement to the project might be to implement support for backends for sending codes.

Right now there's model method . send_login_email() that is called from the view. My suggestion would be to generalize that method(perhaps call it .send_login_code()) to use registered backends specified in settings. This would allow to flexibly plug in additional backends to send login codes via email(default), SMS, push notifications, etc.

Thoughts?

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.