Skip to main content

Django

配置Authok

获取应用密钥

你需要如下信息

  • Domain
  • Client ID
  • Client Secret

配置回调URL

配置 Logout URL

集成 Authok

requirements.txt中添加依赖:

django~=2.1
social-auth-app-django~=3.1
python-jose~=3.0
python-dotenv~=0.9

执行以下命令安装依赖:

pip install -r requirements.txt

创建 Django工程

django-admin startproject webappexample
cd webappexample
python manage.py startapp authok_login

Django设置

webappexample\settings.py
INSTALLED_APPS = [
'social_django',
'<your application name>' # such as 'webappexample'
]
webappexample\settings.py
SOCIAL_AUTH_TRAILING_SLASH = False  # Remove trailing slash from routes
SOCIAL_AUTH_AUTHOK_DOMAIN = 'YOUR_DOMAIN'
SOCIAL_AUTH_AUTHOK_KEY = 'YOUR_CLIENT_ID'
SOCIAL_AUTH_AUTHOK_SECRET = 'YOUR_CLIENT_SECRET'
webappexample\settings.py
SOCIAL_AUTH_AUTHOK_SCOPE = [
'openid',
'profile',
'email'
]

初始化数据库

python manage.py migrate

创建 Authok认证 后端服务

authok_login/authok_backend.py
from urllib import request
from jose import jwt
from social_core.backends.oauth import BaseOAuth2


class Authok(BaseOAuth2):
"""Authok OAuth authentication backend"""
name = 'authok'
SCOPE_SEPARATOR = ' '
ACCESS_TOKEN_METHOD = 'POST'
REDIRECT_STATE = False
EXTRA_DATA = [
('picture', 'picture'),
('email', 'email')
]

def authorization_url(self):
return 'https://' + self.setting('DOMAIN') + '/authorize'

def access_token_url(self):
return 'https://' + self.setting('DOMAIN') + '/oauth/token'

def get_user_id(self, details, response):
"""Return current user id."""
return details['user_id']

def get_user_details(self, response):
# Obtain JWT and the keys to validate the signature
id_token = response.get('id_token')
jwks = request.urlopen('https://' + self.setting('DOMAIN') + '/.well-known/jwks.json')
issuer = 'https://' + self.setting('DOMAIN') + '/'
audience = self.setting('KEY') # CLIENT_ID
payload = jwt.decode(id_token, jwks.read(), algorithms=['RS256'], audience=audience, issuer=issuer)

return {'username': payload['nickname'],
'first_name': payload['name'],
'picture': payload['picture'],
'user_id': payload['sub'],
'email': payload['email']}

在 settings.py 中注册.

webappexample\settings.py
AUTHENTICATION_BACKENDS = {
'YOUR_DJANGO_APP_NAME.authok_backend.Authok',
'django.contrib.auth.backends.ModelBackend'
}
webappexample\settings.py
LOGIN_URL = '/login/authok'
LOGIN_REDIRECT_URL = '/dashboard'

触发认证

authok_login/views.py
from django.shortcuts import render, redirect

def index(request):
user = request.user
if user.is_authenticated:
return redirect(dashboard)
else:
return render(request, 'index.html')

index.html模版中添加 /login/authok链接.

authok_login/templates/index.html
<div class="login-box authok-box before">
<img src="https://i.cloudup.com/StzWWrY34s.png" />
<h3>Authok例子</h3>
<p>零信任身份基础设施,专为开发者打造</p>
<a class="btn btn-primary btn-lg btn-login btn-block" href="/login/authok">登录</a>
</div>

显示用户信息

authok_login/views.py

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
import json

@login_required
def dashboard(request):
user = request.user
authok_user = user.social_auth.get(provider='authok')
userdata = {
'user_id': authok_user.uid,
'name': user.first_name,
'picture': authok_user.extra_data['picture'],
'email': authok_user.extra_data['email'],
}

return render(request, 'dashboard.html', {
'authokUser': authok_user,
'userdata': json.dumps(userdata, indent=4)
})

把以下代码加入dashboard.html以展示用户信息.

authok_login/templates/dashboard.html
<div class="logged-in-box authok-box logged-in">
<h1 id="logo"><img src="//cdn.authok.cn/assets/authok-badge.png" /></h1>
<img class="avatar" src="{{ authokUser.extra_data.picture }}"/>
<h2>Welcome {{ user.username }}</h2>
<pre>{{ userdata }}</pre>
</div>

注销

dashboard.html中添加/logout链接.

authok_login/templates/dashboard.html
<div class="logged-in-box authok-box logged-in">
<h1 id="logo"><img src="//cdn.authok.cn/assets/authok-badge.png" /></h1>
<img class="avatar" src="{{ authokUser.extra_data.picture }}"/>
<h2>Welcome {{ user.username }}</h2>
<pre>{{ userdata }}</pre>
<a class="btn btn-primary btn-lg btn-logout btn-block" href="/logout">Logout</a>
</div>

views.py中添加logout方法.

authok_login/views.py
# ...
from django.contrib.auth import logout as log_out
from django.conf import settings
from django.http import HttpResponseRedirect
from urllib.parse import urlencode

# ...
def logout(request):
log_out(request)
return_to = urlencode({'return_to': request.build_absolute_uri('/')})
logout_url = 'https://%s/v1/logout?client_id=%s&%s' % \
(settings.SOCIAL_AUTH_AUTHOK_DOMAIN, settings.SOCIAL_AUTH_AUTHOK_KEY, return_to)
return HttpResponseRedirect(logout_url)

添加URL映射

authok_login\urls.py
urlpatterns = [
path('', views.index),
path('dashboard', views.dashboard),
path('logout', views.logout),
path('', include('django.contrib.auth.urls')),
path('', include('social_django.urls')),
]

运行例子

python manage.py migrate
python manage.py runserver 3000

可通过 http://localhost:3000 访问应用.