def login(request): ret = None if request.method == 'POST': form = FacebookConnectForm(request.POST) if form.is_valid(): try: token = form.cleaned_data['access_token'] g = GraphAPI(token) facebook_me = g.get_object("me") email = valid_email_or_none(facebook_me.get('email')) social_id = facebook_me['id'] try: account = SocialAccount.objects.get( uid=social_id, provider=FacebookProvider.id) except SocialAccount.DoesNotExist: account = SocialAccount(uid=social_id, provider=FacebookProvider.id) data = dict(email=email, facebook_access_token=token, facebook_me=facebook_me) # some facebook accounts don't have this data data.update((k, v) for (k, v) in facebook_me.items() if k in ['username', 'first_name', 'last_name']) # Don't save partial/temporary accounts that haven't # gone through the full signup yet, as there is no # User attached yet. if account.pk: account.sync(data) ret = complete_social_login(request, data, account) except (GraphAPIError, IOError): pass if not ret: ret = render_authentication_error(request) return ret
def test_get_redir_user_demo(self): payload = {"user": {"username": self.demo["username"]}} self.client.login(username=payload["user"]["username"], password="******") sapp = SocialApp(provider='github', name='Github', client_id='<test>', secret='<test>') sapp.save() sacc = SocialAccount(uid=1001, user=self.test_user, provider="github") sacc.save() stoken = SocialToken(app=sapp, account=sacc, token="test_token") stoken.save() response = self.client.post('/accounts/profile', follow=True) first_url, first_response = response.redirect_chain[0] self.assertEqual( first_url, "/login?status=passed&token=test_token&username=testname&user_id=1001" ) self.client.login(username=payload["user"]["username"], password="******") stoken = SocialToken(app=sapp, account=sacc, token="test_token") stoken.save() response = self.client.post('/accounts/profile', follow=True) first_url, first_response = response.redirect_chain[0] self.assertEqual( first_url, "/login?status=passed&token=test_token&username=testname&user_id=1001" )
def complete_login(self, request, app, token, **kwargs): resp = requests.get( self.profile_url, headers={'Authorization': 'Bearer %s' % token.token}) resp.raise_for_status() extra_data = resp.json() oauth2_client = self.get_oauth2_client() extra_data.update({ 'sso_client_identifier': oauth2_client.identifier, 'sso_client_name': oauth2_client.name, 'sso_client_domain': oauth2_client.domain, }) # We trust the email address; therefore, we will add this login method to any existing user with that email address. # We do so by creating a SocialAccount if it does not exist. email = extra_data[oauth2_client.email_key] try: user = User.objects.get(email=email) except User.DoesNotExist: pass else: object_identifier = {'provider': self.provider_id, 'uid': email} if not SocialAccount.objects.filter(**object_identifier).exists(): social_account = SocialAccount(user_id=user.id, extra_data=extra_data, **object_identifier) social_account.save() login = self.get_provider() \ .sociallogin_from_response(request, extra_data) return login
def complete_login(self, request, app, token, **kwargs): resp = requests.get(self.profile_url, params={ 'access_token': token.token, 'alt': 'json' }) extra_data = resp.json() # extra_data is something of the form: # # {u'family_name': u'Penners', u'name': u'Raymond Penners', # u'picture': u'https://lh5.googleusercontent.com/-GOFYGBVOdBQ/AAAAAAAAAAI/AAAAAAAAAGM/WzRfPkv4xbo/photo.jpg', # u'locale': u'nl', u'gender': u'male', # u'email': u'*****@*****.**', # u'link': u'https://plus.google.com/108204268033311374519', # u'given_name': u'Raymond', u'id': u'108204268033311374519', # u'verified_email': True} # # TODO: We could use verified_email to bypass allauth email verification uid = str(extra_data['id']) account = SocialAccount(extra_data=extra_data, uid=uid, provider=self.provider_id) user = get_adapter() \ .populate_new_user(request, account, email=extra_data.get('email'), last_name=extra_data.get('family_name'), first_name=extra_data.get('given_name')) account.user = user email_addresses = [] email = user_email(user) if email and extra_data.get('verified_email'): email_addresses.append( EmailAddress(email=email, verified=True, primary=True)) return SocialLogin(account, email_addresses=email_addresses)
def persona_login(request): assertion = request.POST.get('assertion', '') audience = request.build_absolute_uri('/') resp = requests.post('https://verifier.login.persona.org/verify', {'assertion': assertion, 'audience': audience}) if resp.json()['status'] != 'okay': return render_authentication_error(request) email = resp.json()['email'] extra_data = resp.json() account = SocialAccount(uid=email, provider=PersonaProvider.id, extra_data=extra_data) account.user = get_adapter() \ .populate_new_user(request, account, email=email) # TBD: Persona e-mail addresses are verified, so we could check if # a matching local user account already exists with an identical # verified e-mail address and short-circuit the social login. Then # again, this holds for all social providers that guarantee # verified e-mail addresses, so if at all, short-circuiting should # probably not be handled here... login = SocialLogin(account) login.state = SocialLogin.state_from_request(request) return complete_social_login(request, login)
def complete_login(self, request, app, token, **kwargs): resp = requests.get(self.profile_url, params={ 'access_token': token.token, 'alt': 'json' }) extra_data = resp.json() # extra_data is something of the form: # # {u'family_name': u'Penners', u'name': u'Raymond Penners', # u'picture': u'https://lh5.googleusercontent.com/-GOFYGBVOdBQ/AAAAAAAAAAI/AAAAAAAAAGM/WzRfPkv4xbo/photo.jpg', # u'locale': u'nl', u'gender': u'male', # u'email': u'*****@*****.**', # u'link': u'https://plus.google.com/108204268033311374519', # u'given_name': u'Raymond', u'id': u'108204268033311374519', # u'verified_email': True} # # TODO: We could use verified_email to bypass allauth email verification uid = str(extra_data['id']) account = SocialAccount(extra_data=extra_data, uid=uid, provider=self.provider_id) user = get_adapter() \ .populate_new_user(request, account, email=extra_data.get('email'), last_name=extra_data.get('family_name'), first_name=extra_data.get('given_name')) account.user = user email_addresses = [] email = user_email(user) if email and extra_data.get('verified_email'): email_addresses.append(EmailAddress(email=email, verified=True, primary=True)) return SocialLogin(account, email_addresses=email_addresses)
def test_get_avatar_url_no_picture_setting(self): extra_data = ''' { "profilePicture": { "displayImage": "urn:li:digitalmediaAsset:12345abcdefgh-12abcd" }, "id": "1234567", "lastName": { "preferredLocale": { "language": "en", "country": "US" }, "localized": { "en_US": "Penners" } }, "firstName": { "preferredLocale": { "language": "en", "country": "US" }, "localized": { "en_US": "Raymond" } } } ''' acc = SocialAccount( extra_data=loads(extra_data), provider='linkedin_oauth2', ) self.assertIsNone(acc.get_avatar_url())
def login(request): ret = None if request.method == 'POST': form = FacebookConnectForm(request.POST) if form.is_valid(): try: token = form.cleaned_data['access_token'] g = GraphAPI(token) facebook_me = g.get_object("me") email = valid_email_or_none(facebook_me.get('email')) social_id = facebook_me['id'] try: account = SocialAccount.objects.get(uid=social_id, provider=FacebookProvider.id) except SocialAccount.DoesNotExist: account = SocialAccount(uid=social_id, provider=FacebookProvider.id) data = dict(email=email, facebook_access_token=token, facebook_me=facebook_me) # some facebook accounts don't have this data data.update((k, v) for (k, v) in facebook_me.items() if k in ['username', 'first_name', 'last_name']) # Don't save partial/temporary accounts that haven't # gone through the full signup yet, as there is no # User attached yet. if account.pk: account.sync(data) ret = complete_social_login(request, data, account) except (GraphAPIError, IOError): pass if not ret: ret = render_authentication_error(request) return ret
def test_fetch_avatar_does_not_overwrite_in_aws(mock_save, db, settings): responses.add(responses.GET, re.compile(r'http://1x1px\.me/.+'), body=open('tests/fixtures/1x1.png', 'rb').read()) mock_save.side_effect = lambda name, *args, **kwargs: name # identity save user1, user2 = UserFactory(), UserFactory() account1 = SocialAccount( provider='google', user=user1, uid='1', extra_data={'picture': 'http://1x1px.me/yszgHjRfq24/photo.jpg'}) account2 = SocialAccount( provider='google', user=user1, uid='1', extra_data={'picture': 'http://1x1px.me/sLbe8rOXpaQ/photo.jpg'}) fetch_avatar(request=None, user=user1, account=account1) fetch_avatar(request=None, user=user2, account=account2) user1.refresh_from_db() user2.refresh_from_db() assert user1.avatar assert user1.avatar != user2.avatar
def persona_login(request): assertion = request.POST.get('assertion', '') audience = request.build_absolute_uri('/') resp = requests.post('https://verifier.login.persona.org/verify', { 'assertion': assertion, 'audience': audience }) if resp.json()['status'] != 'okay': return render_authentication_error(request) email = resp.json()['email'] extra_data = resp.json() account = SocialAccount(uid=email, provider=PersonaProvider.id, extra_data=extra_data) account.user = get_adapter() \ .populate_new_user(request, account, email=email) # TBD: Persona e-mail addresses are verified, so we could check if # a matching local user account already exists with an identical # verified e-mail address and short-circuit the social login. Then # again, this holds for all social providers that guarantee # verified e-mail addresses, so if at all, short-circuiting should # probably not be handled here... login = SocialLogin(account) login.state = SocialLogin.state_from_request(request) return complete_social_login(request, login)
def join(request): current_user = request.session.get('current_user', None) socialaccount_sociallogin = request.session.get('socialaccount_sociallogin', None) if not current_user and not socialaccount_sociallogin: raise Http404 if request.method == 'POST': form = UserForm(request.POST) if form.is_valid(): password = '******'+str(uuid.uuid4()).replace("-", "") # 유저 생성 user = User.objects.create(email=request.POST.get('email'), password=password) mailing_agree = request.POST.get('mailing_agree', None) # 소셜 정보 생성 social_auth = SocialAccount() if current_user: social_user = request.session['current_user']['obj'] social_auth.provider = 'soundcloud' social_auth.uid = social_user['id'] user.username = social_user['username'] user.soundcloud_url = social_user['permalink_url'] user.profile_picture = social_user['avatar_url'] social_auth.user_id = user.id if socialaccount_sociallogin: social_user = request.session['socialaccount_sociallogin']['account'] social_auth.provider = social_user['provider'] social_auth.uid = social_user['uid'] social_auth.user_id = user.id if 'naver' in social_user['provider']: user.username = social_user['extra_data'].get('name', social_user['extra_data']['nickname']) user.profile_picture = social_user['extra_data'].get('profile_image', '') else: user.username = social_user['extra_data'].get('name', '') social_auth.save() if mailing_agree and 'on' in mailing_agree: user.mailing_agree = True user.last_login = datetime.now() user.save() auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # 콜백 # msg = settings.SOCIAL_AUTH_LOGIN_REDIRECT_URL+"#status=success&access_token="+get_user_token(user.id) return auth_redirect(request, "#status=success&access_token="+get_user_token(user.id)) # return redirect('//dopehotz.com'+msg) else: form = UserForm() return render(request, 'accounts/join_form.html', {'form': form, 'main_site' : settings.MAIN_URL})
def _get_sociallogin(user, provider): """ Returns an ready sociallogin object for the given auth provider. """ socialaccount = SocialAccount(user=user, uid='1234', provider=provider) socialaccount.extra_data = {'email': user.email} sociallogin = SocialLogin() sociallogin.account = socialaccount return sociallogin
def test_data_to_str(self): data = { 'emailAddress': '*****@*****.**', 'firstName': 'John', 'id': 'a1b2c3d4e', 'lastName': 'Doe', 'pictureUrl': 'https://media.licdn.com/mpr/foo', 'pictureUrls': {'_total': 1, 'values': ['https://media.licdn.com/foo']}, 'publicProfileUrl': 'https://www.linkedin.com/in/johndoe'} acc = SocialAccount(extra_data=data, provider='linkedin_oauth2') self.assertEqual(acc.get_provider_account().to_str(), 'John Doe')
def _add_surfconext_socialaccount(self, user): random_surfconext_id = str(uuid.uuid4()) extra_data = {"family_name": user.last_name, "sub": random_surfconext_id, "email": user.email, "name": user.get_full_name(), "given_name": user.first_name} socialaccount = SocialAccount(extra_data=extra_data, uid=random_surfconext_id, provider='surf_conext', user=user) socialaccount.save()
def _process_signup(request, data, account): # If email is specified, check for duplicate and if so, no auto signup. auto_signup = app_settings.AUTO_SIGNUP email = data.get('email') if auto_signup: # Let's check if auto_signup is really possible... if email: if account_settings.UNIQUE_EMAIL: if email_address_exists(email): # Oops, another user already has this address. We # cannot simply connect this social account to the # existing user. Reason is that the email adress may # not be verified, meaning, the user may be a hacker # that has added your email address to his account in # the hope that you fall in his trap. We cannot check # on 'email_address.verified' either, because # 'email_address' is not guaranteed to be verified. auto_signup = False # FIXME: We redirect to signup form -- user will # see email address conflict only after posting # whereas we detected it here already. elif account_settings.EMAIL_REQUIRED: # Nope, email is required and we don't have it yet... auto_signup = False if not auto_signup: request.session['socialaccount_signup'] = dict(data=data, account=account) url = reverse('socialaccount_signup') next = request.REQUEST.get('next') if next: url = url + '?' + urlencode(dict(next=next)) ret = HttpResponseRedirect(url) else: # FIXME: There is some duplication of logic inhere # (create user, send email, in active etc..) username = generate_unique_username \ (data.get('username', email or 'user')) u = User(username=username, email=email or '', last_name = data.get('last_name', '')[0:User._meta.get_field('last_name').max_length], first_name = data.get('first_name', '')[0:User._meta.get_field('first_name').max_length]) u.set_unusable_password() u.is_active = not account_settings.EMAIL_VERIFICATION u.save() accountbase = SocialAccount() accountbase.user = u accountbase.save() account.base = accountbase account.sync(data) send_email_confirmation(u, request=request) ret = complete_social_signup(request, u, account) return ret
def _get_sociallogin(user, provider): """ Returns an ready sociallogin object for the given auth provider. """ socialaccount = SocialAccount( user=user, uid='1234', provider=provider, ) socialaccount.extra_data = {'email': user.email} sociallogin = SocialLogin() sociallogin.account = socialaccount return sociallogin
def add_eduid_socialaccount(self, user): random_eduid = "urn:mace:eduid.nl:1.0:d57b4355-c7c6-4924-a944-6172e31e9bbc:{}c14-b952-4d7e-85fd-{}ac5c6f18".format(random.randint(1, 99999), random.randint(1, 9999)) extra_data = {"family_name": user.last_name, "sub": random_eduid, "email": user.email, "name": user.get_full_name(), "given_name": user.first_name} socialaccount = SocialAccount(extra_data=extra_data, uid=random_eduid, provider='edu_id', user=user) socialaccount.save() user.remove_cached_data(['cached_affiliations'])
def complete_login(self, request, app, token): client = VimeoAPI(request, app.client_id, app.secret, self.request_token_url) extra_data = client.get_user_info() uid = extra_data['id'] account = SocialAccount(provider=self.provider_id, extra_data=extra_data, uid=uid) account.user = get_adapter() \ .populate_new_user(request, account, name=extra_data.get('display_name'), username=extra_data.get('username')) return SocialLogin(account)
def complete_login(self, request, app, token, **kwargs): resp = requests.get(self.profile_url, params={'access_token': token.token}) extra_data = resp.json()['data'] uid = str(extra_data['login']) account = SocialAccount(uid=uid, extra_data=extra_data, provider=self.provider_id) account.user = get_adapter().populate_new_user( request, account, username=extra_data['login'], name=extra_data.get('full_name')) return SocialLogin(account)
def complete_login(self, request, app, token): client = TwitterAPI(request, app.client_id, app.secret, self.request_token_url) extra_data = client.get_user_info() uid = extra_data['id'] account = SocialAccount(uid=uid, provider=TwitterProvider.id, extra_data=extra_data) account.user = get_adapter() \ .populate_new_user(request, account, username=extra_data.get('screen_name'), name=extra_data.get('name')) return SocialLogin(account)
def callback(request): client = _openid_consumer(request) response = client.complete(dict(request.REQUEST.items()), request.build_absolute_uri(request.path)) if response.status == consumer.SUCCESS: account = SocialAccount(uid=response.identity_url, provider=OpenIDProvider.id, extra_data={}) account.user = get_adapter().populate_new_user(request, account, email=_get_email_from_response(response)) login = SocialLogin(account) login.state = SocialLogin.unstash_state(request) ret = complete_social_login(request, login) elif response.status == consumer.CANCEL: ret = HttpResponseRedirect(reverse("socialaccount_login_cancelled")) else: ret = render_authentication_error(request) return ret
def complete_login(self, request, app, token, **kwargs): resp = requests.get(self.profile_url, params={'oauth_token': token.token}) extra_data = resp.json() uid = str(extra_data['_id']) account = SocialAccount(uid=uid, extra_data=extra_data, provider=self.provider_id) account.user = get_adapter() \ .populate_new_user(request, account, username=extra_data.get('display_name'), name=extra_data.get('name'), email=extra_data.get('email')) return SocialLogin(account)
def complete_login(self, request, app, token, **kwargs): uid = kwargs.get('response', {}).get('uid') resp = requests.get(self.profile_url, params={'access_token': token.token, 'uid': uid}) extra_data = resp.json() account = SocialAccount(uid=uid, extra_data=extra_data, provider=self.provider_id) account.user = get_adapter() \ .populate_new_user(request, account, username=extra_data.get('screen_name'), name=extra_data.get('name')) return SocialLogin(account)
def test_data_to_str(self): data = { "emailAddress": "*****@*****.**", "firstName": "John", "id": "a1b2c3d4e", "lastName": "Doe", "pictureUrl": "https://media.licdn.com/mpr/foo", "pictureUrls": { "_total": 1, "values": ["https://media.licdn.com/foo"], }, "publicProfileUrl": "https://www.linkedin.com/in/johndoe", } acc = SocialAccount(extra_data=data, provider="linkedin_oauth2") self.assertEqual(acc.get_provider_account().to_str(), "John Doe")
def complete_login(self, request, app, token): client = LinkedInAPI(request, app.client_id, app.secret, self.request_token_url) extra_data = client.get_user_info() uid = extra_data['id'] account = SocialAccount(provider=self.provider_id, extra_data=extra_data, uid=uid) account.user = get_adapter() \ .populate_new_user(request, account, email=extra_data.get('email-address'), first_name=extra_data.get('first-name'), last_name=extra_data.get('last-name')) return SocialLogin(account)
def copy_fb_data(apps, schema_editor): model = apps.get_model('xsd_members', 'MemberProfile') db_alias = schema_editor.connection.alias objects = model.objects.using(db_alias).all() for obj in objects: if obj.facebook_id: sa = SocialAccount( user_id = obj.user.pk, provider = 'facebook', uid = obj.facebook_id, last_login = obj.user.last_login, date_joined = obj.user.date_joined, extra_data = obj.raw_data ) sa.save()
def dispatch(self, request): app = self.adapter.get_app(request) provider_id = self.adapter.provider_id try: uid, data, extra_data = self.adapter.get_user_info(request, app) except OAuthError: return render_authentication_error(request) try: account = SocialAccount.objects.get(provider=provider_id, uid=uid) except SocialAccount.DoesNotExist: account = SocialAccount(provider=provider_id, uid=uid) account.extra_data = extra_data if account.pk: account.save() return complete_social_login(request, data, account)
def complete_login(self, request, app, token, **kwargs): resp = requests.get(self.profile_url, params={'oauth_token': token.token}) extra_data = resp.json() uid = str(extra_data['id']) account = SocialAccount(uid=uid, extra_data=extra_data, provider=self.provider_id) account.user = get_adapter() \ .populate_new_user(request, account, name=extra_data.get('full_name'), username=extra_data.get('username'), email=extra_data.get('email')) return SocialLogin(account)
def _create_social_user(self, emails, provider, uid, token=None): factory = RequestFactory() request = factory.get("/me/login/callback/") request.user = AnonymousUser() SessionMiddleware().process_request(request) MessageMiddleware().process_request(request) user = User( username=emails[0].email.split("@")[0], first_name=emails[0].email.split("@")[0], last_name=emails[0].email.split("@")[1], email=emails[0].email, ) account = SocialAccount(provider=provider, uid=uid) if token is not None: token = SocialToken( token=token, account=account, app=SocialApp.objects.get(provider=provider), ) sociallogin = SocialLogin(account=account, user=user, email_addresses=emails, token=token) complete_social_login(request, sociallogin)
def sociallogin_from_response(self, request, response, **kwargs): """Custom sociallogin from user for person and company models.""" from allauth.socialaccount.models import SocialLogin, SocialAccount adapter = SocialAccountAdapter() uid = self.extract_uid(response) extra_data = self.extract_extra_data(response) common_fields = self.extract_common_fields(response) socialaccount = SocialAccount(extra_data=extra_data, uid=uid, provider=self.id) email_addresses = self.extract_email_addresses(response) self.cleanup_email_addresses(common_fields.get('email'), email_addresses) sociallogin = SocialLogin(account=socialaccount, email_addresses=email_addresses) # user = sociallogin.user = adapter.new_user(request, sociallogin) from .serializers import RegisterSerializer data = RegisterSerializer().validate_account_type(account_type=extra_data['account_type']) if 'C' in data.keys(): user = sociallogin.user = Company() user.user_type = User.COMPANY else: user = sociallogin.user = Person() user.set_unusable_password() adapter.populate_user(request, sociallogin, common_fields) return sociallogin, response
def complete_login(self, request, app, token): resp = requests.get(self.profile_url, { 'access_token': token.token, 'alt': 'json' }) extra_data = resp.json # extra_data is something of the form: # # {u'family_name': u'Penners', u'name': u'Raymond Penners', # u'picture': u'https://lh5.googleusercontent.com/-GOFYGBVOdBQ/AAAAAAAAAAI/AAAAAAAAAGM/WzRfPkv4xbo/photo.jpg', # u'locale': u'nl', u'gender': u'male', # u'email': u'*****@*****.**', # u'link': u'https://plus.google.com/108204268033311374519', # u'given_name': u'Raymond', u'id': u'108204268033311374519', # u'verified_email': True} # # TODO: We could use verified_email to bypass allauth email verification uid = str(extra_data['id']) user = User(email=extra_data.get('email', ''), last_name=extra_data.get('family_name', ''), first_name=extra_data.get('given_name', '')) account = SocialAccount(extra_data=extra_data, uid=uid, provider=self.provider_id, user=user) return SocialLogin(account)
def sociallogin_from_response(self, request, response): """ COPIED FROM https://github.com/pennersr/django-allauth/blob/5b1cbf485fa363ccb87513545e3b98f3c3bd81fa/allauth/socialaccount/providers/base.py#L52 TO PASS SocialApp TO EXTRACT METHODS PER https://github.com/pennersr/django-allauth/issues/1297 """ # NOTE: Avoid loading models at top due to registry boot... from allauth.socialaccount.models import SocialLogin, SocialAccount adapter = get_adapter() app = self.get_app(request) uid = self.extract_uid(response, app) extra_data = self.extract_extra_data(response, app) common_fields = self.extract_common_fields(response, app) socialaccount = SocialAccount(extra_data=extra_data, uid=uid, provider=self.id) email_addresses = self.extract_email_addresses(response, app) self.cleanup_email_addresses(common_fields.get('email'), email_addresses) sociallogin = SocialLogin(account=socialaccount, email_addresses=email_addresses) user = sociallogin.user = adapter.new_user(request, sociallogin) user.set_unusable_password() adapter.populate_user(request, sociallogin, common_fields) return sociallogin
def test_get_social_account_image_linkedin(): account = SocialAccount( extra_data={ 'profilePicture': { 'displayImage~': { 'paging': { 'count': 10, 'start': 0, 'links': [] }, 'elements': [ { 'identifiers': [{ 'identifier': 'https://image.com/image.png', }] }, ], } }, 'id': 's27gBbCPyF', }, provider='linkedin_oauth2', ) assert utils.get_social_account_image( account) == 'https://image.com/image.png'
def test_get_social_account_image_linkedin_no_profile_pic(): account = SocialAccount( extra_data={'id': 's27gBbCPyF'}, provider='linkedin_oauth2', ) assert utils.get_social_account_image(account) is None
def sociallogin_from_response(self, request, response): """ Instantiates and populates a `SocialLogin` model based on the data retrieved in `response`. The method does NOT save the model to the DB. Data for `SocialLogin` will be extracted from `response` with the help of the `.extract_uid()`, `.extract_extra_data()`, `.extract_common_fields()`, and `.extract_email_addresses()` methods. :param request: a Django `HttpRequest` object. :param response: object retrieved via the callback response of the social auth provider. :return: A populated instance of the `SocialLogin` model (unsaved). """ # NOTE: Avoid loading models at top due to registry boot... from allauth.socialaccount.models import SocialLogin, SocialAccount adapter = get_adapter(request) uid = self.extract_uid(response) extra_data = self.extract_extra_data(response) common_fields = self.extract_common_fields(response) socialaccount = SocialAccount(extra_data=extra_data, uid=uid, provider=self.id) email_addresses = self.extract_email_addresses(response) self.cleanup_email_addresses(common_fields.get('email'), email_addresses) sociallogin = SocialLogin(account=socialaccount, email_addresses=email_addresses) user = sociallogin.user = adapter.new_user(request, sociallogin) user.set_unusable_password() adapter.populate_user(request, sociallogin, common_fields) return sociallogin
def fb_complete_login(request, app, token): resp = requests.get('https://graph.facebook.com/me', params={'access_token': token.token}) extra_data = resp.json() uid = extra_data['id'] account = SocialAccount(uid=uid, provider=FacebookProvider.id, extra_data=extra_data) account.user = get_adapter() \ .populate_new_user(request, account, email=extra_data.get('email'), username=extra_data.get('username'), first_name=extra_data.get('first_name'), last_name=extra_data.get('last_name')) return SocialLogin(account)
def test_pre_social_login_error_for_unmatched_login(self): """ When we suspect the signup form is used as a connection form, abort. https://bugzil.la/1063830 """ # Set up a GitHub SocialLogin in the session github_account = SocialAccount.objects.get(user__username='******') github_login = SocialLogin(account=github_account, user=github_account.user) request = self.rf.get('/') session = self.client.session session['socialaccount_sociallogin'] = github_login.serialize() session.save() request.session = session messages = self.get_messages(request) # Set up an un-matching alternate SocialLogin for request other_account = SocialAccount(user=self.user_model(), provider='other', uid='*****@*****.**') other_login = SocialLogin(account=other_account) self.assertRaises(ImmediateHttpResponse, self.adapter.pre_social_login, request, other_login) queued_messages = list(messages) eq_(len(queued_messages), 1) eq_(django_messages.ERROR, queued_messages[0].level)
def test_pre_social_login_same_provider(self): """ pre_social_login passes if existing provider is the same. I'm not sure what the real-world counterpart of this is. Logging in with a different GitHub account? Needed for branch coverage. """ # Set up a GitHub SocialLogin in the session github_account = SocialAccount.objects.get(user__username='******') github_login = SocialLogin(account=github_account, user=github_account.user) request = self.rf.get('/') session = self.client.session session['sociallogin_provider'] = 'github' session['socialaccount_sociallogin'] = github_login.serialize() session.save() request.session = session # Set up an un-matching GitHub SocialLogin for request github2_account = SocialAccount(user=self.user_model(), provider='github', uid=github_account.uid + '2') github2_login = SocialLogin(account=github2_account) self.adapter.pre_social_login(request, github2_login) eq_(request.session['sociallogin_provider'], 'github')
def test_pre_social_login_error_for_unmatched_login(self): """ https://bugzil.la/1063830 """ # Set up a GitHub SocialLogin in the session github_account = SocialAccount.objects.get(user__username='******') github_login = SocialLogin(account=github_account) request = self.rf.get('/') session = self.client.session session['socialaccount_sociallogin'] = github_login.serialize() session.save() request.session = session messages = self.get_messages(request) # Set up an un-matching Persona SocialLogin for request persona_account = SocialAccount(user=User(), provider='persona', uid='*****@*****.**') persona_login = SocialLogin(account=persona_account) self.assertRaises(ImmediateHttpResponse, self.adapter.pre_social_login, request, persona_login) queued_messages = list(messages) eq_(len(queued_messages), 1) eq_(django_messages.ERROR, queued_messages[0].level)
def get_or_create_user(payload, oidc=False): user_id = payload.get('sub') if not user_id: msg = _('Invalid payload.') raise exceptions.AuthenticationFailed(msg) try_again = False try: user = _try_create_or_update(user_id, payload, oidc) except IntegrityError: # If we get an integrity error, it probably meant a race # condition with another process. Another attempt should # succeed. try_again = True if try_again: # We try again without catching exceptions this time. user = _try_create_or_update(user_id, payload, oidc) # If allauth.socialaccount is installed, create the SocialAcount # that corresponds to this user. Otherwise logins through # allauth will not work for the user later on. if 'allauth.socialaccount' in settings.INSTALLED_APPS: from allauth.socialaccount.models import SocialAccount, EmailAddress if oidc: provider_name = 'helsinki_oidc' else: provider_name = 'helsinki' args = {'provider': provider_name, 'uid': user_id} try: account = SocialAccount.objects.get(**args) assert account.user_id == user.id except SocialAccount.DoesNotExist: account = SocialAccount(**args) account.extra_data = payload account.user = user account.save() try: email = EmailAddress.objects.get(email__iexact=user.email) assert email.user == user except EmailAddress.DoesNotExist: email = EmailAddress(email=user.email.lower(), primary=True, user=user, verified=True) email.save() return user
def test_get_redir_user_demo(self): payload = {"user": {"username": self.demo["username"]}} self.client.login(username=payload["user"]["username"], password="******") sapp = SocialApp(provider='github', name='Github', client_id='<test>', secret='<test>') sapp.save() sacc = SocialAccount(uid=1001, user=self.test_user, provider="github") sacc.save() stoken = SocialToken(app=sapp, account=sacc, token="test_token") stoken.save() response = self.client.post('/accounts/profile', follow=True) first_url, first_response = response.redirect_chain[0] self.assertEqual(first_url, "/login?status=passed&token=test_token&username=testname&user_id=1001") self.client.login(username=payload["user"]["username"], password="******") stoken = SocialToken(app=sapp, account=sacc, token="test_token") stoken.save() response = self.client.post('/accounts/profile', follow=True) first_url, first_response = response.redirect_chain[0] self.assertEqual(first_url, "/login?status=passed&token=test_token&username=testname&user_id=1001")
def complete_login(self, request, app, token, **kwargs): uid = kwargs['response']['user_id'] resp = requests.get(self.profile_url, params={'access_token': token.token, 'fields': ','.join(USER_FIELDS), 'user_ids': uid}) resp.raise_for_status() extra_data = resp.json()['response'][0] account = SocialAccount(extra_data=extra_data, uid=str(uid), provider=self.provider_id) account.user = get_adapter() \ .populate_new_user(request, account, last_name=extra_data.get('family_name'), username=extra_data.get('screen_name'), first_name=extra_data.get('given_name')) return SocialLogin(account)
def complete_login(self, request, app, token, **kwargs): provider = registry.by_id(app.provider) site = provider.get_site() resp = requests.get(self.profile_url, params={'access_token': token.token, 'key': app.key, 'site': site}) extra_data = resp.json()['items'][0] # `user_id` varies if you use the same account for # e.g. StackOverflow and ServerFault. Therefore, we pick # `account_id`. uid = str(extra_data['account_id']) account = SocialAccount(uid=uid, extra_data=extra_data, provider=self.provider_id) account.user = get_adapter() \ .populate_new_user(request, account, username=extra_data.get('display_name')) return SocialLogin(account)
def dispatch(self, request): if 'error' in request.GET or not 'code' in request.GET: # TODO: Distinguish cancel from error return render_authentication_error(request) app = self.adapter.get_app(self.request) client = self.get_client(request, app) provider_id = self.adapter.provider_id try: access_token = client.get_access_token(request.GET['code']) uid, data, extra_data = self.adapter.get_user_info(request, app, access_token) except OAuth2Error: return render_authentication_error(request) # TODO: DRY, duplicates OAuth logic try: account = SocialAccount.objects.get(provider=provider_id, uid=uid) except SocialAccount.DoesNotExist: account = SocialAccount(provider=provider_id, uid=uid) account.extra_data = extra_data if account.pk: account.save() return complete_social_login(request, data, account)
def complete_login(self, request, app, token, email_addresses=[]): client = TwitterAPI(request, app.client_id, app.secret, self.request_token_url) extra_data = client.get_user_info() uid = extra_data['id'] user = User.objects.filter(username=extra_data.get('screen_name')) if user: return user else: user = get_adapter() \ .populate_new_user(username=extra_data.get('screen_name'), name=extra_data.get('name')) user.save() account = SocialAccount(user=user, uid=uid, provider=TwitterProvider.id, extra_data=extra_data) account.save() application = SocialApp.objects.get(secret=app.secret) sample_token = SocialToken.objects.filter(app=application, account=account) if sample_token: token = sample_token[0] else: token = SocialToken(app=application, account=account, token=request.session["oauth_api.twitter.com_access_token"]["oauth_token"], token_secret=request.session["oauth_api.twitter.com_access_token"][ "oauth_token_secret"]) token.save() mail = send_email_confirmation(request=request, user=user, signup=True) return SocialLogin(account=account, token=token, email_addresses=email_addresses)