├── LICENSE
├── MANIFEST.in
├── README.rst
├── firebase_auth
├── authentication.py
├── exceptions.py
└── mixins.py
└── setup.py
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Copyright (c) 2018, Felix Cornelius
3 |
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without modification,
7 | are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice,
10 | this list of conditions and the following disclaimer.
11 | * Redistributions in binary form must reproduce the above copyright notice,
12 | this list of conditions and the following disclaimer in the documentation
13 | and/or other materials provided with the distribution.
14 | * Neither the name of django-firebase-auth nor the names of its contributors
15 | may be used to endorse or promote products derived from this software
16 | without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include LICENSE
2 | include README.rst
3 | recursive-include firebase_auth *
4 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | =====
2 | django-firebase-auth
3 | =====
4 |
5 | django-firebase-auth is a authentication provider for Google's `Firebase Authentication Service `_ which blends right into django-rest-framework.
6 | Simply setup your Firebase keyfile location and mark views which need authentication with the FirebaseAuthMixin authentication class.
7 |
8 |
9 | Detailed documentation is in the "docs" directory.
10 |
11 | Installation
12 | -----------
13 |
14 | Install via pip::
15 |
16 | pip install django-firebase-auth
17 |
18 | (This will also install dependencies `django-rest-framework `_ and `firebase-admin `_.)
19 |
20 | Quick start
21 | -----------
22 |
23 | 1. Add "firebase_auth" to your INSTALLED_APPS setting like this::
24 |
25 | INSTALLED_APPS = [
26 | ...
27 | 'firebase_auth',
28 | ]
29 |
30 | 2. Specify a location for your Firebase keyfile with the settings::
31 |
32 | KEYFILES_DIR = os.path.join(BASE_DIR, 'keyfiles')
33 | FIREBASE_KEY = '.json'
34 |
35 | And place the json key inside BASE_DIR/keyfiles.
36 |
37 | 3. Either set FirebaseAuthentication as the global default authentication class in settings, like::
38 |
39 | REST_FRAMEWORK = {
40 | 'DEFAULT_AUTHENTICATION_CLASSES': ('firebase_auth.authentication.FirebaseAuthentication', ),
41 | }
42 |
43 | Or extend specific views from FirebaseAuthMixin, like::
44 |
45 | from firebase_auth import FirebaseAuthMixin
46 | class MyModelViewSet(FirebaseAuthMixin, viewsets.ModelViewSet)
47 | ...
48 |
49 | Note that the auth mixin has to be the first class extended by the view.
50 |
51 | 4. Create your users with the Firebase user ID as user ID.
52 | Inside your views, you can access the user reference like you're used to with request.user
53 |
54 |
55 |
--------------------------------------------------------------------------------
/firebase_auth/authentication.py:
--------------------------------------------------------------------------------
1 | from rest_framework import authentication
2 | from django.contrib.auth.models import User
3 | from rest_framework import exceptions
4 | import firebase_admin
5 | from firebase_admin import credentials
6 | from firebase_admin import auth
7 | import os
8 | from django.conf import settings
9 |
10 | json = os.path.join(settings.KEYFILES_DIR, settings.FIREBASE_KEY)
11 | cred = credentials.Certificate(json)
12 | default_app = firebase_admin.initialize_app(cred)
13 |
14 |
15 | class FirebaseAuthentication(authentication.BaseAuthentication):
16 | def authenticate(self, request):
17 | id_token = request.META.get('HTTP_AUTHORIZATION')
18 | decoded_token = None
19 | try:
20 | decoded_token = auth.verify_id_token(id_token)
21 | except Exception as e:
22 | pass
23 |
24 | if not id_token or not decoded_token:
25 | return None
26 |
27 | uid = decoded_token.get('uid')
28 | try:
29 | user = User.objects.get(username=uid)
30 | except User.DoesNotExist:
31 | raise exceptions.AuthenticationFailed('The user does not exist')
32 |
33 | return (user, None)
34 |
--------------------------------------------------------------------------------
/firebase_auth/exceptions.py:
--------------------------------------------------------------------------------
1 | from rest_framework import status
2 | from rest_framework.exceptions import APIException
3 |
4 | class NoAuthToken(APIException):
5 | status_code = status.HTTP_401_UNAUTHORIZED
6 | default_detail = 'No authentication token provided'
7 | default_code = 'no_auth_token'
8 |
9 | class InvalidAuthToken(APIException):
10 | status_code = status.HTTP_401_UNAUTHORIZED
11 | default_detail = 'Invalid authentication token provided'
12 | default_code = 'invalid_token'
13 |
14 | class FirebaseError(APIException):
15 | status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
16 | default_detail = 'The user provided with the auth token is not a valid Firebase user, it has no Firebase UID'
17 | default_code = 'no_firebase_uid'
18 |
19 |
--------------------------------------------------------------------------------
/firebase_auth/mixins.py:
--------------------------------------------------------------------------------
1 | from .authentication import FirebaseAuthentication
2 | from rest_framework.permissions import IsAuthenticated
3 |
4 | class FirebaseAuthMixin():
5 | permission_classes = (IsAuthenticated,)
6 | authentication_classes = (FirebaseAuthentication,)
7 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import os
2 | from setuptools import find_packages, setup
3 |
4 | with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
5 | README = readme.read()
6 |
7 | # allow setup.py to be run from any path
8 | os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
9 |
10 | setup(
11 | name='django-firebase-auth',
12 | version='0.4',
13 | packages=find_packages(),
14 | install_requires=[
15 | 'firebase-admin',
16 | 'djangorestframework'
17 | ],
18 | include_package_data=True,
19 | license='BSD License',
20 | description='A django-rest-framework authentication provider for Google\'s Firebase Authentication Service',
21 | long_description=README,
22 | author='Felix Cornelius',
23 | author_email='mail@felixcornelius.de',
24 | classifiers=[
25 | 'Environment :: Web Environment',
26 | 'Framework :: Django',
27 | 'Framework :: Django :: 1.11',
28 | 'Intended Audience :: Developers',
29 | 'License :: OSI Approved :: BSD License',
30 | 'Operating System :: OS Independent',
31 | 'Programming Language :: Python',
32 | 'Programming Language :: Python :: 3.5',
33 | 'Programming Language :: Python :: 3.6',
34 | 'Topic :: Internet :: WWW/HTTP',
35 | 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
36 | ],
37 | )
38 |
--------------------------------------------------------------------------------