diff options
author | Bill Prin <waprin@gmail.com> | 2016-09-20 12:28:47 -0700 |
---|---|---|
committer | Jon Wayne Parrott <jonwayne@google.com> | 2016-09-20 12:28:47 -0700 |
commit | 3f9fdbd5a3e590e6e53e42a59ca96d1010c0cec7 (patch) | |
tree | 32c100ce32f226b9810622913b01f63d60e34140 | |
parent | 8a6e3b2a34561fb575ceecbb0f598347d47786e3 (diff) | |
download | oauth2client-3f9fdbd5a3e590e6e53e42a59ca96d1010c0cec7.tar.gz |
Add Django Samples (#636)
Contains two sets of samples - one for the “Google auth” system and one for the “Django
user auth” system.
19 files changed, 543 insertions, 0 deletions
diff --git a/samples/django/README.md b/samples/django/README.md new file mode 100644 index 0000000..27c0fda --- /dev/null +++ b/samples/django/README.md @@ -0,0 +1,21 @@ +# Django Samples + +These two sample Django apps provide a skeleton for the two main use cases of the +`oauth2client.contrib.django_util` helpers. + +Please see the +[core docs](https://oauth2client.readthedocs.io/en/latest/) for more information and usage examples. + +## google_user + +This is the simpler use case of the library. It assumes you are using Google OAuth as your primary +authorization and authentication mechanism for your application. Users log in with their Google ID +and their OAuth2 credentials are stored inside the session. + +## django_user + +This is the use case where the application is already using the Django authorization system and +has a Django model with a `django.contrib.auth.models.User` field, and would like to attach +a Google OAuth2 credentials object to that model. Users have to login, and then can login with +their Google account to associate the Google account with the user in the Django system. +Credentials will be stored in the Django ORM backend. diff --git a/samples/django/django_user/manage.py b/samples/django/django_user/manage.py new file mode 100755 index 0000000..1a30708 --- /dev/null +++ b/samples/django/django_user/manage.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# Copyright 2016 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myoauth.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/samples/django/django_user/myoauth/__init__.py b/samples/django/django_user/myoauth/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/samples/django/django_user/myoauth/__init__.py diff --git a/samples/django/django_user/myoauth/settings.py b/samples/django/django_user/myoauth/settings.py new file mode 100644 index 0000000..5ef2f99 --- /dev/null +++ b/samples/django/django_user/myoauth/settings.py @@ -0,0 +1,115 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +import os + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'eiw+mvmua#98n@p2xq+c#liz@r2&#-s07nkgz)+$zcl^o4$-$o' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + +# Application definition + +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'polls', + 'oauth2client.contrib.django_util', +) + +MIDDLEWARE_CLASSES = ( + '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', + 'django.middleware.security.SecurityMiddleware', +) + +ROOT_URLCONF = 'myoauth.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'myoauth.wsgi.application' + +# Database +# https://docs.djangoproject.com/en/1.8/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + +# Internationalization +# https://docs.djangoproject.com/en/1.8/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.8/howto/static-files/ + +STATIC_URL = '/static/' + +GOOGLE_OAUTH2_CLIENT_ID = 'YOUR_CLIENT_ID' + +GOOGLE_OAUTH2_CLIENT_SECRET = 'YOUR_CLIENT_SECRET' + +GOOGLE_OAUTH2_SCOPES = ( + 'email', 'profile') + +GOOGLE_OAUTH2_STORAGE_MODEL = { + 'model': 'polls.models.CredentialsModel', + 'user_property': 'user_id', + 'credentials_property': 'credential', +} + +LOGIN_URL = '/login' diff --git a/samples/django/django_user/myoauth/urls.py b/samples/django/django_user/myoauth/urls.py new file mode 100644 index 0000000..6636b4e --- /dev/null +++ b/samples/django/django_user/myoauth/urls.py @@ -0,0 +1,30 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.conf import urls +from django.contrib import admin +import django.contrib.auth.views +from polls import views + +import oauth2client.contrib.django_util.site as django_util_site + + +urlpatterns = [ + urls.url(r'^$', views.index), + urls.url(r'^profile_required$', views.get_profile_required), + urls.url(r'^profile_enabled$', views.get_profile_optional), + urls.url(r'^admin/', urls.include(admin.site.urls)), + urls.url(r'^login', django.contrib.auth.views.login, name="login"), + urls.url(r'^oauth2/', urls.include(django_util_site.urls)), +] diff --git a/samples/django/django_user/myoauth/wsgi.py b/samples/django/django_user/myoauth/wsgi.py new file mode 100644 index 0000000..39ee648 --- /dev/null +++ b/samples/django/django_user/myoauth/wsgi.py @@ -0,0 +1,21 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myoauth.settings") + +application = get_wsgi_application() diff --git a/samples/django/django_user/polls/__init__.py b/samples/django/django_user/polls/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/samples/django/django_user/polls/__init__.py diff --git a/samples/django/django_user/polls/models.py b/samples/django/django_user/polls/models.py new file mode 100644 index 0000000..563f66e --- /dev/null +++ b/samples/django/django_user/polls/models.py @@ -0,0 +1,23 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.contrib.auth.models import User +from django.db import models + +from oauth2client.contrib.django_util.models import CredentialsField + + +class CredentialsModel(models.Model): + user_id = models.OneToOneField(User) + credential = CredentialsField() diff --git a/samples/django/django_user/polls/templates/registration/login.html b/samples/django/django_user/polls/templates/registration/login.html new file mode 100644 index 0000000..c43450e --- /dev/null +++ b/samples/django/django_user/polls/templates/registration/login.html @@ -0,0 +1,45 @@ +<!-- +# Copyright 2016 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--> + +{% if form.errors %} +<p>Your username and password didn't match. Please try again.</p> +{% endif %} + +{% if next %} +{% if user.is_authenticated %} +<p>Your account doesn't have access to this page. To proceed, + please login with an account that has access.</p> +{% else %} +<p>Please login to see this page.</p> +{% endif %} +{% endif %} + +<form method="post" action="{% url 'login' %}"> + {% csrf_token %} + <table> + <tr> + <td>{{ form.username.label_tag }}</td> + <td>{{ form.username }}</td> + </tr> + <tr> + <td>{{ form.password.label_tag }}</td> + <td>{{ form.password }}</td> + </tr> + </table> + + <input type="submit" value="login" /> + <input type="hidden" name="next" value="{{ next }}" /> +</form> diff --git a/samples/django/django_user/polls/views.py b/samples/django/django_user/polls/views.py new file mode 100644 index 0000000..5888330 --- /dev/null +++ b/samples/django/django_user/polls/views.py @@ -0,0 +1,41 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.http import HttpResponse + +from oauth2client.contrib.django_util import decorators + + +def index(request): + return HttpResponse("Hello world!") + + +@decorators.oauth_required +def get_profile_required(request): + resp, content = request.oauth.http.request( + 'https://www.googleapis.com/plus/v1/people/me') + return HttpResponse(content) + + +@decorators.oauth_enabled +def get_profile_optional(request): + if request.oauth.has_credentials(): + # this could be passed into a view + # request.oauth.http is also initialized + return HttpResponse('User email: {}'.format( + request.oauth.credentials.id_token['email'])) + else: + return HttpResponse( + 'Here is an OAuth Authorize link:<a href="{}">Authorize</a>' + .format(request.oauth.get_authorize_redirect())) diff --git a/samples/django/django_user/requirements.txt b/samples/django/django_user/requirements.txt new file mode 100644 index 0000000..b42af1f --- /dev/null +++ b/samples/django/django_user/requirements.txt @@ -0,0 +1,3 @@ +Django==1.10.0 +oauth2client==3.0.0 +jsonpickle==0.9.3 diff --git a/samples/django/google_user/manage.py b/samples/django/google_user/manage.py new file mode 100755 index 0000000..1a30708 --- /dev/null +++ b/samples/django/google_user/manage.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# Copyright 2016 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myoauth.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/samples/django/google_user/myoauth/__init__.py b/samples/django/google_user/myoauth/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/samples/django/google_user/myoauth/__init__.py diff --git a/samples/django/google_user/myoauth/settings.py b/samples/django/google_user/myoauth/settings.py new file mode 100644 index 0000000..e08661d --- /dev/null +++ b/samples/django/google_user/myoauth/settings.py @@ -0,0 +1,107 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +import os + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'eiw+mvmua#98n@p2xq+c#liz@r2&#-s07nkgz)+$zcl^o4$-$o' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + +# Application definition + +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'polls', + 'oauth2client.contrib.django_util', +) + +MIDDLEWARE_CLASSES = ( + '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', + 'django.middleware.security.SecurityMiddleware', +) + +ROOT_URLCONF = 'myoauth.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'myoauth.wsgi.application' + +# Database +# https://docs.djangoproject.com/en/1.8/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + +# Internationalization +# https://docs.djangoproject.com/en/1.8/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.8/howto/static-files/ + +STATIC_URL = '/static/' + +GOOGLE_OAUTH2_CLIENT_ID = 'YOUR_CLIENT_ID' + +GOOGLE_OAUTH2_CLIENT_SECRET = 'YOUR_CLIENT_SECRET' + +GOOGLE_OAUTH2_SCOPES = ( + 'email', 'profile') diff --git a/samples/django/google_user/myoauth/urls.py b/samples/django/google_user/myoauth/urls.py new file mode 100644 index 0000000..4d3d0a1 --- /dev/null +++ b/samples/django/google_user/myoauth/urls.py @@ -0,0 +1,26 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.conf import urls +from polls import views + +import oauth2client.contrib.django_util.site as django_util_site + + +urlpatterns = [ + urls.url(r'^$', views.index), + urls.url(r'^profile_required$', views.get_profile_required), + urls.url(r'^profile_enabled$', views.get_profile_optional), + urls.url(r'^oauth2/', urls.include(django_util_site.urls)) +] diff --git a/samples/django/google_user/myoauth/wsgi.py b/samples/django/google_user/myoauth/wsgi.py new file mode 100644 index 0000000..39ee648 --- /dev/null +++ b/samples/django/google_user/myoauth/wsgi.py @@ -0,0 +1,21 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myoauth.settings") + +application = get_wsgi_application() diff --git a/samples/django/google_user/polls/__init__.py b/samples/django/google_user/polls/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/samples/django/google_user/polls/__init__.py diff --git a/samples/django/google_user/polls/views.py b/samples/django/google_user/polls/views.py new file mode 100644 index 0000000..e4b9119 --- /dev/null +++ b/samples/django/google_user/polls/views.py @@ -0,0 +1,41 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django import http + +from oauth2client.contrib.django_util import decorators + + +def index(request): + return http.HttpResponse("Hello world!") + + +@decorators.oauth_required +def get_profile_required(request): + resp, content = request.oauth.http.request( + 'https://www.googleapis.com/plus/v1/people/me') + return http.HttpResponse(content) + + +@decorators.oauth_enabled +def get_profile_optional(request): + if request.oauth.has_credentials(): + # this could be passed into a view + # request.oauth.http is also initialized + return http.HttpResponse('User email: {}'.format( + request.oauth.credentials.id_token['email'])) + else: + return http.HttpResponse( + 'Here is an OAuth Authorize link:<a href="{}">Authorize</a>' + .format(request.oauth.get_authorize_redirect())) diff --git a/samples/django/google_user/requirements.txt b/samples/django/google_user/requirements.txt new file mode 100644 index 0000000..b42af1f --- /dev/null +++ b/samples/django/google_user/requirements.txt @@ -0,0 +1,3 @@ +Django==1.10.0 +oauth2client==3.0.0 +jsonpickle==0.9.3 |