def _set_auth_cookie(self, request, response): if getattr(settings, 'ENABLE_SHIB_LOGIN', False): key_prefix = 'shib_' elif getattr(settings, 'ENABLE_KRB5_LOGIN', False): key_prefix = 'krb5_' else: key_prefix = '' api_token = get_api_token(request, key_prefix) response.set_cookie('seahub_auth', request.user.username + '@' + api_token.key, domain=settings.SESSION_COOKIE_DOMAIN)
def work_weixin_oauth_callback(request): if not work_weixin_oauth_check(): return render_error(request, _('Feature is not enabled.')) code = request.GET.get('code', None) state = request.GET.get('state', None) if state != request.session.get('work_weixin_oauth_state', None) or not code: logger.error( 'can not get right code or state from work weixin request') return render_error(request, _('Error, please contact administrator.')) access_token = get_work_weixin_access_token() if not access_token: logger.error('can not get work weixin access_token') return render_error(request, _('Error, please contact administrator.')) data = { 'access_token': access_token, 'code': code, } api_response = requests.get(WORK_WEIXIN_GET_USER_INFO_URL, params=data) api_response_dic = handler_work_weixin_api_response(api_response) if not api_response_dic: logger.error('can not get work weixin user info') return render_error(request, _('Error, please contact administrator.')) if not api_response_dic.get('UserId', None): logger.error('can not get UserId in work weixin user info response') return render_error(request, _('Error, please contact administrator.')) user_id = api_response_dic.get('UserId') uid = WORK_WEIXIN_UID_PREFIX + user_id work_weixin_user = SocialAuthUser.objects.get_by_provider_and_uid( WORK_WEIXIN_PROVIDER, uid) if work_weixin_user: email = work_weixin_user.username is_new_user = False else: email = gen_user_virtual_id() SocialAuthUser.objects.add(email, WORK_WEIXIN_PROVIDER, uid) is_new_user = True try: user = auth.authenticate(remote_user=email) except User.DoesNotExist: user = None if not user: return render_error( request, _('Error, new user registration is not allowed, please contact administrator.' )) # update user info if is_new_user or WORK_WEIXIN_USER_INFO_AUTO_UPDATE: user_info_data = { 'access_token': access_token, 'userid': user_id, } user_info_api_response = requests.get(WORK_WEIXIN_GET_USER_PROFILE_URL, params=user_info_data) user_info_api_response_dic = handler_work_weixin_api_response( user_info_api_response) if user_info_api_response_dic: api_user = user_info_api_response_dic api_user['username'] = email api_user['contact_email'] = api_user['email'] update_work_weixin_user_info(api_user) if not user.is_active: return render_error( request, _('Your account is created successfully, please wait for administrator to activate your account.' )) # User is valid. Set request.user and persist user in the session # by logging the user in. request.user = user auth.login(request, user) # generate auth token for Seafile client api_token = get_api_token(request) # redirect user to page response = HttpResponseRedirect( request.session.get('work_weixin_oauth_redirect', '/')) response.set_cookie('seahub_auth', user.username + '@' + api_token.key) return response
def oauth_callback(request): """ Step 3: Retrieving an access token. The user has been redirected back from the provider to your registered callback URL. With this redirection comes an authorization code included in the redirect URL. We will use that to obtain an access token. """ session = OAuth2Session(client_id=CLIENT_ID, scope=SCOPE, state=request.session.get('oauth_state', None), redirect_uri=REDIRECT_URL) try: token = session.fetch_token( TOKEN_URL, client_secret=CLIENT_SECRET, authorization_response=request.get_full_path()) if session._client.__dict__['token'].has_key('user_id'): # used for sjtu.edu.cn # https://xjq12311.gitbooks.io/sjtu-engtc/content/ user_id = session._client.__dict__['token']['user_id'] user_info_resp = session.get(USER_INFO_URL + '?user_id=%s' % user_id) else: user_info_url = USER_INFO_URL if ACCESS_TOKEN_IN_URI: code = request.GET.get('code') user_info_url = USER_INFO_URL + '?access_token=%s&code=%s' % ( token['access_token'], code) user_info_resp = session.get(user_info_url) except Exception as e: logger.error(e) return render_error(request, _('Error, please contact administrator.')) def format_user_info(user_info_resp): logger.info('user info resp: %s' % user_info_resp.text) error = False user_info = {} user_info_json = user_info_resp.json() for item, attr in ATTRIBUTE_MAP.items(): required, user_attr = attr value = user_info_json.get(item, '') if value: # ccnet email if user_attr == 'email': user_info[user_attr] = value if is_valid_email(str(value)) else \ '%s@%s' % (str(value), PROVIDER_DOMAIN) else: user_info[user_attr] = value elif required: error = True return user_info, error user_info, error = format_user_info(user_info_resp) if error: logger.error('Required user info not found.') logger.error(user_info) return render_error(request, _('Error, please contact administrator.')) # seahub authenticate user email = user_info['email'] try: user = auth.authenticate(remote_user=email) except User.DoesNotExist: user = None if not user or not user.is_active: logger.error('User %s not found or inactive.' % email) # a page for authenticate user failed return render_error(request, _(u'User %s not found.') % email) # User is valid. Set request.user and persist user in the session # by logging the user in. request.user = user auth.login(request, user) # update user's profile name = user_info['name'] if user_info.has_key('name') else '' contact_email = user_info['contact_email'] if \ user_info.has_key('contact_email') else '' profile = Profile.objects.get_profile_by_user(email) if not profile: profile = Profile(user=email) if name: profile.nickname = name.strip() profile.save() if contact_email: profile.contact_email = contact_email.strip() profile.save() # generate auth token for Seafile client api_token = get_api_token(request) # redirect user to home page response = HttpResponseRedirect(request.session['oauth_redirect']) response.set_cookie('seahub_auth', email + '@' + api_token.key) return response
def weixin_oauth_callback(request): if not ENABLE_WEIXIN: return render_error(request, _('Error, please contact administrator.')) state = request.GET.get('state', '') if not state or state != request.session.get('weixin_oauth_login_state', ''): logger.error('invalid state') return render_error(request, _('Error, please contact administrator.')) # get access_token and user openid parameters = { 'appid': WEIXIN_OAUTH_APP_ID, 'secret': WEIXIN_OAUTH_APP_SECRET, 'code': request.GET.get('code'), 'grant_type': WEIXIN_OAUTH_GRANT_TYPE, } access_token_url = WEIXIN_OAUTH_ACCESS_TOKEN_URL + '?' + urllib.parse.urlencode(parameters) access_token_json = requests.get(access_token_url).json() openid = access_token_json.get('openid', '') access_token = access_token_json.get('access_token', '') if not access_token or not openid: logger.error('invalid access_token or openid') logger.error(access_token_url) logger.error(access_token_json) return render_error(request, _('Error, please contact administrator.')) # login user in auth_user = SocialAuthUser.objects.get_by_provider_and_uid('weixin', openid) if auth_user: email = auth_user.username else: email = gen_user_virtual_id() SocialAuthUser.objects.add(email, 'weixin', openid) try: user = auth.authenticate(remote_user=email) except User.DoesNotExist: user = None except Exception as e: logger.error(e) return render_error(request, _('Error, please contact administrator.')) if not user or not user.is_active: return render_error(request, _('User %s not found or inactive.') % email) request.user = user auth.login(request, user) # get user profile info parameters = { 'access_token': access_token, 'openid': openid, } user_info_url = WEIXIN_OAUTH_USER_INFO_URL + '?' + urllib.parse.urlencode(parameters) user_info_resp = requests.get(user_info_url).json() name = user_info_resp['nickname'] if 'nickname' in user_info_resp else '' name = name.encode('raw_unicode_escape').decode('utf-8') if name: profile = Profile.objects.get_profile_by_user(email) if not profile: profile = Profile(user=email) profile.nickname = name.strip() profile.save() avatar_url = user_info_resp['headimgurl'] if 'headimgurl' in user_info_resp else '' try: image_name = 'dingtalk_avatar' image_file = requests.get(avatar_url).content avatar = Avatar.objects.filter(emailuser=email, primary=True).first() avatar = avatar or Avatar(emailuser=email, primary=True) avatar_file = ContentFile(image_file) avatar_file.name = image_name avatar.avatar = avatar_file avatar.save() except Exception as e: logger.error(e) # generate auth token for Seafile client api_token = get_api_token(request) # redirect user to home page response = HttpResponseRedirect(request.session['weixin_oauth_login_redirect']) response.set_cookie('seahub_auth', email + '@' + api_token.key) return response
def dingtalk_callback(request): if not ENABLE_DINGTALK: return render_error(request, _('Error, please contact administrator.')) state = request.GET.get('state', '') if not state or state != request.session.get('dingtalk_login_state', ''): logger.error('invalid state') return render_error(request, _('Error, please contact administrator.')) timestamp = str(int(time.time() * 1000)).encode('utf-8') appsecret = DINGTALK_QR_CONNECT_APP_SECRET.encode('utf-8') signature = base64.b64encode( hmac.new(appsecret, timestamp, digestmod=sha256).digest()) parameters = { 'accessKey': DINGTALK_QR_CONNECT_APP_ID, 'timestamp': timestamp, 'signature': signature, } code = request.GET.get('code') data = {"tmp_auth_code": code} full_user_info_url = DINGTALK_QR_CONNECT_USER_INFO_URL + '?' + urllib.parse.urlencode( parameters) user_info_resp = requests.post(full_user_info_url, data=json.dumps(data)) user_info = user_info_resp.json()['user_info'] # seahub authenticate user if 'unionid' not in user_info: logger.error('Required user info not found.') logger.error(user_info) return render_error(request, _('Error, please contact administrator.')) auth_user = SocialAuthUser.objects.get_by_provider_and_uid( 'dingtalk', user_info['unionid']) if auth_user: email = auth_user.username else: email = gen_user_virtual_id() SocialAuthUser.objects.add(email, 'dingtalk', user_info['unionid']) try: user = auth.authenticate(remote_user=email) except User.DoesNotExist: user = None except Exception as e: logger.error(e) return render_error(request, _('Error, please contact administrator.')) if not user or not user.is_active: return render_error(request, _('User %s not found or inactive.') % email) # User is valid. Set request.user and persist user in the session # by logging the user in. request.user = user request.session['remember_me'] = DINGTALK_QR_CONNECT_LOGIN_REMEMBER_ME auth.login(request, user) # update user's profile name = user_info['nick'] if 'nick' in user_info else '' if name: profile = Profile.objects.get_profile_by_user(email) if not profile: profile = Profile(user=email) profile.nickname = name.strip() profile.save() user_detail_info = dingtalk_get_detailed_user_info(user_info['unionid']) contact_email = user_detail_info.get('email', '') if contact_email: profile.contact_email = contact_email profile.save() # generate auth token for Seafile client api_token = get_api_token(request) # redirect user to home page response = HttpResponseRedirect( request.session.get('dingtalk_login_redirect', '/')) response.set_cookie('seahub_auth', email + '@' + api_token.key) return response
def weixin_oauth_callback(request): if not weixin_check(): return render_error(request, _('Feature is not enabled.')) code = request.GET.get('code', None) state = request.GET.get('state', None) weixin_oauth_state = request.session.get('weixin_oauth_state', None) weixin_oauth_redirect = request.session.get('weixin_oauth_redirect', redirect_to) org_id = request.session.get('weixin_oauth_org_id', None) is_mobile_weixin = request.session.get('weixin_oauth_is_mobile_weixin', False) # clear session try: del request.session['weixin_oauth_state'] del request.session['weixin_oauth_redirect'] del request.session['weixin_oauth_org_id'] del request.session['weixin_oauth_is_mobile_weixin'] except Exception as e: logger.warning(e) # get api user info if state != weixin_oauth_state or not code: logger.error('can not get right code or state from weixin request') return render_error(request, _('Error, please contact administrator.')) access_token, openid = get_weixin_access_token_and_openid( code, is_mobile_weixin) if not access_token or not openid: logger.error('can not get weixin access_token or openid') return render_error(request, _('Error, please contact administrator.')) weixin_api_user_info = get_weixin_api_user_info(access_token, openid) if not weixin_api_user_info: return render_error(request, _('Error, please contact administrator.')) # main user_id = weixin_api_user_info.get('unionid') uid = WEIXIN_UID_PREFIX + user_id weixin_user = SocialAuthUser.objects.get_by_provider_and_uid( WEIXIN_PROVIDER, uid) if weixin_user: email = weixin_user.username is_new_user = False else: email = None is_new_user = True try: user = auth.authenticate(remote_user=email) except User.DoesNotExist: user = None if not user: return render_error( request, _('Error, new user registration is not allowed, please contact administrator.' )) # bind username = user.username if is_new_user: SocialAuthUser.objects.add(username, WEIXIN_PROVIDER, uid) # org invite for new user if org_id: if is_new_user: ccnet_api.add_org_user(org_id, username, int(False)) else: return render_error(request, '仅限新用户加入机构') # update user info if is_new_user or WEIXIN_USER_INFO_AUTO_UPDATE: api_user = weixin_api_user_info api_user['username'] = username update_weixin_user_info(api_user) if not user.is_active: return render_error( request, _('Your account is created successfully, please wait for administrator to activate your account.' )) # User is valid. Set request.user and persist user in the session # by logging the user in. request.user = user request.session['remember_me'] = REMEMBER_ME auth.login(request, user) # generate auth token for Seafile client api_token = get_api_token(request) # redirect user to page response = HttpResponseRedirect(weixin_oauth_redirect) response.set_cookie('seahub_auth', user.username + '@' + api_token.key) return response
def login(request, next_page=None, required=False): """Forwards to CAS login URL or verifies CAS ticket""" service_url = get_service_url(request, next_page) client = get_cas_client(service_url=service_url, request=request) if not next_page and settings.CAS_STORE_NEXT and 'CASNEXT' in request.session: next_page = request.session['CASNEXT'] del request.session['CASNEXT'] if not next_page: next_page = get_redirect_url(request) if request.method == 'POST' and request.POST.get('logoutRequest'): clean_sessions(client, request) return HttpResponseRedirect(next_page) # backward compability for django < 2.0 is_user_authenticated = False if sys.version_info >= (3, 0): bool_type = bool else: bool_type = bool if isinstance(request.user.is_authenticated, bool_type): is_user_authenticated = request.user.is_authenticated else: is_user_authenticated = request.user.is_authenticated if is_user_authenticated: if settings.CAS_LOGGED_MSG is not None: message = settings.CAS_LOGGED_MSG % request.user.get_username() messages.success(request, message) return HttpResponseRedirect(next_page) ticket = request.GET.get('ticket') if ticket: user = authenticate(ticket=ticket, service=service_url, request=request) pgtiou = request.session.get("pgtiou") if user is not None: if not request.session.exists(request.session.session_key): request.session.create() auth_login(request, user) SessionTicket.objects.create( session_key=request.session.session_key, ticket=ticket) if pgtiou and settings.CAS_PROXY_CALLBACK: # Delete old PGT ProxyGrantingTicket.objects.filter( user=user, session_key=request.session.session_key).delete() # Set new PGT ticket try: pgt = ProxyGrantingTicket.objects.get(pgtiou=pgtiou) pgt.user = user pgt.session_key = request.session.session_key pgt.save() except ProxyGrantingTicket.DoesNotExist: pass if settings.CAS_LOGIN_MSG is not None: name = user.get_username() message = settings.CAS_LOGIN_MSG % name messages.success(request, message) api_token = get_api_token(request, '') response = HttpResponseRedirect(next_page) response.set_cookie('seahub_auth', user.username + '@' + api_token.key, domain=settings.SESSION_COOKIE_DOMAIN) return response elif settings.CAS_RETRY_LOGIN or required: return HttpResponseRedirect(client.get_login_url()) else: raise PermissionDenied('Login failed.') else: if settings.CAS_STORE_NEXT: request.session['CASNEXT'] = next_page return HttpResponseRedirect(client.get_login_url())