diff --git a/apps/authentication/views/dingtalk.py b/apps/authentication/views/dingtalk.py index 03a6e8eeb..ed1d50c9a 100644 --- a/apps/authentication/views/dingtalk.py +++ b/apps/authentication/views/dingtalk.py @@ -10,16 +10,16 @@ from django.views import View from rest_framework.exceptions import APIException from rest_framework.permissions import AllowAny, IsAuthenticated -from authentication.decorators import post_save_next_to_session_if_guard_redirect, pre_save_next_to_session from authentication import errors from authentication.const import ConfirmType +from authentication.decorators import post_save_next_to_session_if_guard_redirect, pre_save_next_to_session from authentication.mixins import AuthMixin from authentication.notifications import OAuthBindMessage from authentication.permissions import UserConfirmation from common.sdk.im.dingtalk import URL, DingTalk from common.utils import get_logger from common.utils.common import get_request_ip -from common.utils.django import get_object_or_none, reverse, safe_next_url +from common.utils.django import get_object_or_none, reverse from common.utils.random import random_string from common.views.mixins import PermissionsMixin, UserConfirmRequiredExceptionMixin from users.models import User @@ -237,7 +237,7 @@ class DingTalkOAuthLoginCallbackView(AuthMixin, DingTalkOAuthMixin, View): appsecret=settings.DINGTALK_APPSECRET, agentid=settings.DINGTALK_AGENTID ) - userid, __ = dingtalk.get_user_id_by_code(code) + userid, __ = dingtalk.get_user_id_by_code_for_oauth(code) if not userid: # 正常流程不会出这个错误,hack 行为 msg = _('Failed to get user from DingTalk') diff --git a/apps/common/sdk/im/dingtalk/__init__.py b/apps/common/sdk/im/dingtalk/__init__.py index 2740b456a..cb6075749 100644 --- a/apps/common/sdk/im/dingtalk/__init__.py +++ b/apps/common/sdk/im/dingtalk/__init__.py @@ -1,4 +1,5 @@ import base64 +import hashlib import hmac import time @@ -16,7 +17,7 @@ def sign(secret, data): digest = hmac.HMAC( key=secret.encode('utf8'), msg=data.encode('utf8'), - digestmod=hmac._hashlib.sha256 + digestmod=hashlib.sha256 ).digest() signature = base64.standard_b64encode(digest).decode('utf8') # signature = urllib.parse.quote(signature, safe='') @@ -33,6 +34,7 @@ class URL: OAUTH_CONNECT = 'https://oapi.dingtalk.com/connect/oauth2/sns_authorize' GET_USER_ACCESSTOKEN = 'https://api.dingtalk.com/v1.0/oauth2/userAccessToken' GET_USER_INFO = 'https://api.dingtalk.com/v1.0/contact/users/me' + GET_USERINFO_BYCODE = "https://oapi.dingtalk.com/sns/getuserinfo_bycode" GET_TOKEN = 'https://oapi.dingtalk.com/gettoken' SEND_MESSAGE_BY_TEMPLATE = 'https://oapi.dingtalk.com/topapi/message/corpconversation/sendbytemplate' SEND_MESSAGE = 'https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2' @@ -145,6 +147,14 @@ class DingTalk: headers={'x-acs-dingtalk-access-token': token}, check_errcode_is_0=False) return user + def get_user_id_by_code_for_oauth(self, code): + # https://open.dingtalk.com/document/orgapp/use-a-dingtalk-account-to-log-on-to-a-third-party + user = self._request.post(URL.GET_USERINFO_BYCODE, json={"tmp_auth_code": code}, + check_errcode_is_0=False, with_sign=True) + unionid = user["user_info"]['unionid'] + userid = self.get_userid_by_unionid(unionid) + return userid, None + def get_user_id_by_code(self, code): user_info = self.get_userinfo_bycode(code) unionid = user_info['unionId']