Django Rest Framework 后端的 Ionic Google 社交身份验证
Ionic Google social authentication to Django Rest Framework backend
我正在尝试让社交身份验证适用于我的移动应用程序(Android 上的 Ionic 应用程序)。 Django 休息框架后端 rest_framework_jwt、social_django 和 rest_social_auth.
在我的 Ionic 应用程序上,我使用的是 satellizer.js,但是,我无法使用 InAppBrowser,所以现在我尝试使用 cordova-plugin-googleplus[=57= 执行以下操作]:
步骤#1(上client/app)
if (provider == 'google') {
// Use Google API Natively to get tokens and user info
window.plugins.googleplus.login(
{
// TODO Get the WebClient from App settings
'webClientId': '[*.myclientid]', // optional clientId of your Web application from Credentials settings of your project - On Android, this MUST be included to get an idToken. On iOS, it is not required.
'offline': true, // optional, but requires the webClientId - if set to true the plugin will also return a serverAuthCode, which can be used to grant offline access to a non-Google server
}) ................
结果: 这让我得到了一个有效的响应,其中包含 idToken、serverAuthCode,和一个 userId.
步骤#2
我不确定下一步是什么。最初,我打算尝试使用 Django rest_social_auth 从我的 client/app:
中执行以下操作
POST /api/login/social/
含数据(json)
provider=google&code=ASLKDJASLDKJASLD
本来应该 return 一个 JWT 令牌 (from my understanding of the docs),但是,它没有传递 JWTAuthMixin
因为没有值 return 来自在那个 Mixin 中调用 get_authorization_header(request).split()
。这意味着除了 400 错误外,没有任何内容被 return 编辑到我的 client/app。
我是否应该在传递我的 idToken 或 serverAuthCode 时向我的 Ionic 应用程序 POST 添加 header? 或者我是不是站在错误的一边曲目...
对于这个授权流程有什么实施建议吗?
到目前为止,我执行了以下操作并且有效。
1.关于 app/client
(客户端使用satellizer.js和cordova-plugin-googleplus)
if (provider == 'google') {
// Use Google API Natively to get tokens and user info
window.plugins.googleplus.login(
{
// TODO Get the WebClient from App settings
'webClientId': '*[googleclientid]*.apps.googleusercontent.com',
'offline': true
},
function (obj) {
$http.post(SERVER.url + '[MY BACKEND URL]' + '/google-oauth2/', {code: obj.idToken, servAuthCode: obj.serverAuthCode})
.success(function(data){
$auth.setToken(data.jwt_token);
/.. Do something ../
})
.error(function(data){
console.log("There was an error" + JSON.stringify(data));
});
},
function (msg) {
// TODO Set Error states
console.error('error: ' + msg);
}
);
}
总结
- 应用程序调用 Google 加 API
googleplus.login
方法(发送我的 webClientId)
- 我post登录到我的Django后端后从google获得的结果idToken和serverAuthCode。
2。我的后端方法
URL
我的app/client命中了url(r'^[MY BACKEND URL]/(?P<backend>[\w-]+)/$', ObtainAuthToken.as_view(), ),
查看
这会调用以下视图和函数:
class ObtainAuthToken(APIView):
permission_classes = (AllowAny,)
def post(self, request, backend):
data = request.data
user_tokenID = data['code']
server_auth_code = data['servAuthCode']
if user_tokenID and server_auth_code and verify_google_user_token_ID(user_tokenID):
# Get Google OAuth credentials for the verified GOOGLE user.
credentials = settings.GOOGLE_FLOW.step2_exchange(server_auth_code)
# Here we call PSA to authenticate like we would if we used PSA on server side.
user = register_by_access_token(request, backend, token=credentials.access_token)
# If user is active we get or create the REST token and send it back with user data
if user and user.is_active:
# Generate JWT token for user and pass back to client
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
return JsonResponse({'id': user.id, 'name': user.username, 'jwt_token': token})
return JsonResponse({'status':'false','error':'Bad Credentials, check the Access Token and/or the UID'},
status=403)
def verify_google_user_token_ID(user_tokenID):
try:
google_http_request = google.auth.transport.requests.Request()
idinfo = verify_token(user_tokenID, request=google_http_request,
audience=settings.SOCIAL_AUTH_GOOGLE_OAUTH2_FULL_KEY)
# Or, if multiple clients access the backend server:
if idinfo['aud'] not in [settings.GOOGLE_APP_ID_ANDROID, settings.GOOGLE_APP_ID_WEB]:
raise crypt.AppIdentityError("Unrecognized client.")
if idinfo['iss'] not in ['accounts.google.com', 'https://accounts.google.com']:
raise crypt.AppIdentityError("Wrong issuer.")
return True
except crypt.AppIdentityError as e:
# Invalid token
return False
@psa('social:complete')
def register_by_access_token(request, backend, token):
backend = social_core.backends.google.GoogleOAuth2()
user = backend.do_auth(access_token=token, backend=backend)
if user:
return user
else:
return None
3。回到客户端
我的客户端然后查看响应并获取返回的 JWT 并使用 $auth.setToken(data.jwt_token);
将其加载到内存中
我认为这暂时可行,但我仍然需要处理令牌刷新和撤销等问题。
我正在尝试让社交身份验证适用于我的移动应用程序(Android 上的 Ionic 应用程序)。 Django 休息框架后端 rest_framework_jwt、social_django 和 rest_social_auth.
在我的 Ionic 应用程序上,我使用的是 satellizer.js,但是,我无法使用 InAppBrowser,所以现在我尝试使用 cordova-plugin-googleplus[=57= 执行以下操作]:
步骤#1(上client/app)
if (provider == 'google') {
// Use Google API Natively to get tokens and user info
window.plugins.googleplus.login(
{
// TODO Get the WebClient from App settings
'webClientId': '[*.myclientid]', // optional clientId of your Web application from Credentials settings of your project - On Android, this MUST be included to get an idToken. On iOS, it is not required.
'offline': true, // optional, but requires the webClientId - if set to true the plugin will also return a serverAuthCode, which can be used to grant offline access to a non-Google server
}) ................
结果: 这让我得到了一个有效的响应,其中包含 idToken、serverAuthCode,和一个 userId.
步骤#2
我不确定下一步是什么。最初,我打算尝试使用 Django rest_social_auth 从我的 client/app:
中执行以下操作POST /api/login/social/
含数据(json)
provider=google&code=ASLKDJASLDKJASLD
本来应该 return 一个 JWT 令牌 (from my understanding of the docs),但是,它没有传递 JWTAuthMixin
因为没有值 return 来自在那个 Mixin 中调用 get_authorization_header(request).split()
。这意味着除了 400 错误外,没有任何内容被 return 编辑到我的 client/app。
我是否应该在传递我的 idToken 或 serverAuthCode 时向我的 Ionic 应用程序 POST 添加 header? 或者我是不是站在错误的一边曲目...
对于这个授权流程有什么实施建议吗?
到目前为止,我执行了以下操作并且有效。
1.关于 app/client
(客户端使用satellizer.js和cordova-plugin-googleplus)
if (provider == 'google') {
// Use Google API Natively to get tokens and user info
window.plugins.googleplus.login(
{
// TODO Get the WebClient from App settings
'webClientId': '*[googleclientid]*.apps.googleusercontent.com',
'offline': true
},
function (obj) {
$http.post(SERVER.url + '[MY BACKEND URL]' + '/google-oauth2/', {code: obj.idToken, servAuthCode: obj.serverAuthCode})
.success(function(data){
$auth.setToken(data.jwt_token);
/.. Do something ../
})
.error(function(data){
console.log("There was an error" + JSON.stringify(data));
});
},
function (msg) {
// TODO Set Error states
console.error('error: ' + msg);
}
);
}
总结
- 应用程序调用 Google 加 API
googleplus.login
方法(发送我的 webClientId) - 我post登录到我的Django后端后从google获得的结果idToken和serverAuthCode。
2。我的后端方法
URL
我的app/client命中了url(r'^[MY BACKEND URL]/(?P<backend>[\w-]+)/$', ObtainAuthToken.as_view(), ),
查看
这会调用以下视图和函数:
class ObtainAuthToken(APIView):
permission_classes = (AllowAny,)
def post(self, request, backend):
data = request.data
user_tokenID = data['code']
server_auth_code = data['servAuthCode']
if user_tokenID and server_auth_code and verify_google_user_token_ID(user_tokenID):
# Get Google OAuth credentials for the verified GOOGLE user.
credentials = settings.GOOGLE_FLOW.step2_exchange(server_auth_code)
# Here we call PSA to authenticate like we would if we used PSA on server side.
user = register_by_access_token(request, backend, token=credentials.access_token)
# If user is active we get or create the REST token and send it back with user data
if user and user.is_active:
# Generate JWT token for user and pass back to client
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
return JsonResponse({'id': user.id, 'name': user.username, 'jwt_token': token})
return JsonResponse({'status':'false','error':'Bad Credentials, check the Access Token and/or the UID'},
status=403)
def verify_google_user_token_ID(user_tokenID):
try:
google_http_request = google.auth.transport.requests.Request()
idinfo = verify_token(user_tokenID, request=google_http_request,
audience=settings.SOCIAL_AUTH_GOOGLE_OAUTH2_FULL_KEY)
# Or, if multiple clients access the backend server:
if idinfo['aud'] not in [settings.GOOGLE_APP_ID_ANDROID, settings.GOOGLE_APP_ID_WEB]:
raise crypt.AppIdentityError("Unrecognized client.")
if idinfo['iss'] not in ['accounts.google.com', 'https://accounts.google.com']:
raise crypt.AppIdentityError("Wrong issuer.")
return True
except crypt.AppIdentityError as e:
# Invalid token
return False
@psa('social:complete')
def register_by_access_token(request, backend, token):
backend = social_core.backends.google.GoogleOAuth2()
user = backend.do_auth(access_token=token, backend=backend)
if user:
return user
else:
return None
3。回到客户端
我的客户端然后查看响应并获取返回的 JWT 并使用 $auth.setToken(data.jwt_token);
我认为这暂时可行,但我仍然需要处理令牌刷新和撤销等问题。