Пример #1
0
 def oauth_request(self, token, url, extra_params=None):
     extra_params = extra_params or {}
     scope = GOOGLE_OAUTH_SCOPE + setting('GOOGLE_OAUTH_EXTRA_SCOPE', [])
     extra_params.update({
         'scope': ' '.join(scope),
     })
     if not self.registered():
         xoauth_displayname = setting('GOOGLE_DISPLAY_NAME', 'Social Auth')
         extra_params['xoauth_displayname'] = xoauth_displayname
     return super(GoogleOAuth, self).oauth_request(token, url, extra_params)
Пример #2
0
 def oauth_request(self, token, url, extra_params=None):
     extra_params = extra_params or {}
     scope = GOOGLE_OAUTH_SCOPE + setting('GOOGLE_OAUTH_EXTRA_SCOPE', [])
     extra_params.update({
         'scope': ' '.join(scope),
     })
     if not self.registered():
         xoauth_displayname = setting('GOOGLE_DISPLAY_NAME', 'Social Auth')
         extra_params['xoauth_displayname'] = xoauth_displayname
     return super(GoogleOAuth, self).oauth_request(token, url, extra_params)
Пример #3
0
def save_status_to_session(request, auth, pipeline_index, *args, **kwargs):
    """Saves current social-auth status to session."""
    next_entry = setting('SOCIAL_AUTH_PIPELINE_RESUME_ENTRY')

    if next_entry and next_entry in PIPELINE:
        idx = PIPELINE.index(next_entry)
    else:
        idx = pipeline_index + 1

    data = auth.to_session_dict(idx, *args, **kwargs)
    name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline')
    request.session[name] = data
Пример #4
0
def validate_whitelists(backend, email):
    """
    Validates allowed domains and emails against the following settings:
        GOOGLE_WHITE_LISTED_DOMAINS
        GOOGLE_WHITE_LISTED_EMAILS

    All domains and emails are allowed if setting is an empty list.
    """
    emails = setting('GOOGLE_WHITE_LISTED_EMAILS', [])
    domains = setting('GOOGLE_WHITE_LISTED_DOMAINS', [])
    if emails and email in emails:
        return  # you're good
    if domains and email.split('@', 1)[1] not in domains:
        raise AuthFailed(backend, 'Domain not allowed')
Пример #5
0
def validate_whitelists(backend, email):
    """
    Validates allowed domains and emails against the following settings:
        GOOGLE_WHITE_LISTED_DOMAINS
        GOOGLE_WHITE_LISTED_EMAILS

    All domains and emails are allowed if setting is an empty list.
    """
    emails = setting('GOOGLE_WHITE_LISTED_EMAILS', [])
    domains = setting('GOOGLE_WHITE_LISTED_DOMAINS', [])
    if emails and email in emails:
        return  # you're good
    if domains and email.split('@', 1)[1] not in domains:
        raise AuthFailed(backend, 'Domain not allowed')
Пример #6
0
class YahooOAuthBackend(OAuthBackend):
    """Yahoo OAuth authentication backend"""
    name = 'yahoo-oauth'

    EXTRA_DATA = [
        ('guid', 'id'),
        ('access_token', 'access_token'),
        ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))
    ]

    def get_user_id(self, details, response):
        return response['guid']

    def get_user_details(self, response):
        """Return user details from Yahoo Profile"""
        fname = response.get('givenName')
        lname = response.get('familyName')
        if 'emails' in response:
            email = response.get('emails')[0]['handle']
        else:
            email = ''
        return {USERNAME:     response.get('nickname'),
                'email':      email,
                'fullname':   '%s %s' % (fname, lname),
                'first_name': fname,
                'last_name':  lname}
Пример #7
0
def get_backends(force_load=False):
    """
    Entry point to the BACKENDS cache. If BACKENDSCACHE hasn't been
    populated, each of the modules referenced in
    AUTHENTICATION_BACKENDS is imported and checked for a BACKENDS
    definition and if enabled, added to the cache.

    Previously all backends were attempted to be loaded at
    import time of this module, which meant that backends that subclass
    bases found in this module would not have the chance to be loaded
    by the time they were added to this module's BACKENDS dict. See:
    https://github.com/omab/django-social-auth/issues/204

    This new approach ensures that backends are allowed to subclass from
    bases in this module and still be picked up.

    A force_load boolean arg is also provided so that get_backend
    below can retry a requested backend that may not yet be discovered.
    """
    if not BACKENDSCACHE or force_load:
        for auth_backend in setting('AUTHENTICATION_BACKENDS'):
            mod, cls_name = auth_backend.rsplit('.', 1)
            module = import_module(mod)
            backend = getattr(module, cls_name)

            if issubclass(backend, SocialAuthBackend):
                name = backend.name
                backends = getattr(module, 'BACKENDS', {})
                if name in backends and backends[name].enabled():
                    BACKENDSCACHE[name] = backends[name]
    return BACKENDSCACHE
Пример #8
0
 def auth_extra_arguments(self):
     """Return extra arguments needed on auth process, setting is per
     backend and defined by:
         <backend name in uppercase>_AUTH_EXTRA_ARGUMENTS.
     """
     backend_name = self.AUTH_BACKEND.name.upper().replace('-', '_')
     return setting(backend_name + '_AUTH_EXTRA_ARGUMENTS', {})
Пример #9
0
 def request_token_extra_arguments(self):
     """Return extra arguments needed on request-token process,
     setting is per backend and defined by:
         <backend name in uppercase>_REQUEST_TOKEN_EXTRA_ARGUMENTS.
     """
     backend_name = self.AUTH_BACKEND.name.upper().replace('-', '_')
     return setting(backend_name + '_REQUEST_TOKEN_EXTRA_ARGUMENTS', {})
Пример #10
0
class YaruBackend(OAuthBackend):
    """Yandex OAuth authentication backend"""
    name = 'yaru'
    EXTRA_DATA = [
        ('id', 'id'),
        ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))
    ]

    def get_user_details(self, response):
        """Return user details from Yandex account"""
        name = response['name']
        last_name = ''

        if ' ' in name:
            names = name.split(' ')
            last_name = names[0]
            first_name = names[1]
        else:
            first_name = name

        return {
            USERNAME: get_username_from_url(response.get('links')),
            'email':  response.get('email', ''),
            'first_name': first_name,
            'last_name': last_name,
        }
Пример #11
0
 def get_user_id(self, details, response):
     """Use google email or id as unique id"""
     user_id = super(GoogleOAuth2Backend, self).get_user_id(details,
                                                            response)
     if setting('GOOGLE_OAUTH2_USE_UNIQUE_USER_ID', False):
         return response['id']
     return user_id
Пример #12
0
class EvernoteBackend(OAuthBackend):
    """
    Evernote OAuth authentication backend.

    Possible Values:
       {'edam_expires': ['1367525289541'],
        'edam_noteStoreUrl': [
            'https://sandbox.evernote.com/shard/s1/notestore'
        ],
        'edam_shard': ['s1'],
        'edam_userId': ['123841'],
        'edam_webApiUrlPrefix': ['https://sandbox.evernote.com/shard/s1/'],
        'oauth_token': [
            'S=s1:U=1e3c1:E=13e66dbee45:C=1370f2ac245:P=185:A=my_user:'******'H=411443c5e8b20f8718ed382a19d4ae38'
        ]}
    """
    name = 'evernote'

    EXTRA_DATA = [('access_token', 'access_token'),
                  ('oauth_token', 'oauth_token'),
                  ('edam_noteStoreUrl', 'store_url'),
                  ('edam_expires', setting('SOCIAL_AUTH_EXPIRATION',
                                           'expires'))]

    def get_user_details(self, response):
        """Return user details from Evernote account"""
        return {
            USERNAME: response['edam_userId'],
            'email': '',
        }

    def get_user_id(self, details, response):
        return response['edam_userId']
Пример #13
0
    def auth_complete(self, *args, **kwargs):
        """Performs check of authentication in VKontakte, returns User if
        succeeded"""
        app_cookie = 'vk_app_' + self.APP_ID

        if not 'id' in self.request.GET or \
           not app_cookie in self.request.COOKIES:
            raise ValueError('VKontakte authentication is not completed')

        cookie_dict = dict(
            item.split('=')
            for item in self.request.COOKIES[app_cookie].split('&'))
        check_str = ''.join(item + '=' + cookie_dict[item]
                            for item in ['expire', 'mid', 'secret', 'sid'])

        hash = md5(check_str + setting('VKONTAKTE_APP_SECRET')).hexdigest()

        if hash != cookie_dict['sig'] or int(cookie_dict['expire']) < time():
            raise ValueError('VKontakte authentication failed: invalid hash')
        else:
            kwargs.update({
                'auth': self,
                'response': self.user_data(cookie_dict['mid']),
                self.AUTH_BACKEND.name: True
            })
            return authenticate(*args, **kwargs)
Пример #14
0
    def expiration_datetime(self):
        """Return provider session live seconds. Returns a timedelta ready to
        use with session.set_expiry().

        If provider returns a timestamp instead of session seconds to live, the
        timedelta is inferred from current time (using UTC timezone). None is
        returned if there's no value stored or it's invalid.
        """
        name = setting('SOCIAL_AUTH_EXPIRATION', 'expires')
        if self.extra_data and name in self.extra_data:
            try:
                expires = int(self.extra_data.get(name))
            except (ValueError, TypeError):
                return None

            now = datetime.now()
            now_timestamp = time.mktime(now.timetuple())

            # Detect if expires is a timestamp
            if expires > now_timestamp:  # expires is a datetime
                return datetime.utcfromtimestamp(expires) \
                               .replace(tzinfo=utc) - \
                       now.replace(tzinfo=utc)
            else:  # expires is a timedelta
                return timedelta(seconds=expires)
Пример #15
0
    def expiration_datetime(self):
        """Return provider session live seconds. Returns a timedelta ready to
        use with session.set_expiry().

        If provider returns a timestamp instead of session seconds to live, the
        timedelta is inferred from current time (using UTC timezone). None is
        returned if there's no value stored or it's invalid.
        """
        name = setting('SOCIAL_AUTH_EXPIRATION', 'expires')
        if self.extra_data and name in self.extra_data:
            try:
                expires = int(self.extra_data.get(name))
            except (ValueError, TypeError):
                return None

            now = datetime.now()
            now_timestamp = time.mktime(now.timetuple())

            # Detect if expires is a timestamp
            if expires > now_timestamp:  # expires is a datetime
                return datetime.utcfromtimestamp(expires) \
                               .replace(tzinfo=utc) - \
                       now.replace(tzinfo=utc)
            else:  # expires is a timedelta
                return timedelta(seconds=expires)
Пример #16
0
    def extra_data(self, user, uid, response, details):
        """Return defined extra data names to store in extra_data field.
        Settings will be inspected to get more values names that should be
        stored on extra_data field. Setting name is created from current
        backend name (all uppercase) plus _SREG_EXTRA_DATA and
        _AX_EXTRA_DATA because values can be returned by SimpleRegistration
        or AttributeExchange schemas.

        Both list must be a value name and an alias mapping similar to
        SREG_ATTR, OLD_AX_ATTRS or AX_SCHEMA_ATTRS
        """
        name = self.name.replace('-', '_').upper()
        sreg_names = setting(name + '_SREG_EXTRA_DATA')
        ax_names = setting(name + '_AX_EXTRA_DATA')
        data = self.values_from_response(response, sreg_names, ax_names)
        return data
Пример #17
0
 def get_user_id(self, details, response):
     """Use google email or id as unique id"""
     user_id = super(GoogleOAuth2Backend,
                     self).get_user_id(details, response)
     if setting('GOOGLE_OAUTH2_USE_UNIQUE_USER_ID', False):
         return response['id']
     return user_id
Пример #18
0
class LiveBackend(OAuthBackend):
    name = 'live'

    EXTRA_DATA = [
        ('id', 'id'),
        ('access_token', 'access_token'),
        ('reset_token', 'reset_token'),
        ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires')),
        ('email', 'email'),
        ('first_name', 'first_name'),
        ('last_name', 'last_name'),
    ]

    def get_user_id(self, details, response):
        return response['id']

    def get_user_details(self, response):
        """Return user details from Live Connect account"""
        try:
            email = response['emails']['account']
        except KeyError:
            email = ''

        return {
            USERNAME: response.get('name'),
            'email': email,
            'first_name': response.get('first_name'),
            'last_name': response.get('last_name')
        }
Пример #19
0
    def auth_complete(self, *args, **kwargs):
        """Performs check of authentication in VKontakte, returns User if
        succeeded"""
        app_cookie = 'vk_app_' + self.APP_ID

        if not 'id' in self.request.GET or \
           not app_cookie in self.request.COOKIES:
            raise ValueError('VKontakte authentication is not completed')

        cookie_dict = dict(item.split('=') for item in
                                self.request.COOKIES[app_cookie].split('&'))
        check_str = ''.join(item + '=' + cookie_dict[item]
                                for item in ['expire', 'mid', 'secret', 'sid'])

        hash = md5(check_str + setting('VKONTAKTE_APP_SECRET')).hexdigest()

        if hash != cookie_dict['sig'] or int(cookie_dict['expire']) < time():
            raise ValueError('VKontakte authentication failed: invalid hash')
        else:
            kwargs.update({
                'auth': self,
                'response': self.user_data(cookie_dict['mid']),
                self.AUTH_BACKEND.name: True
            })
            return authenticate(*args, **kwargs)
Пример #20
0
 def build_absolute_uri(self, path=None):
     """Build absolute URI for given path. Replace http:// schema with
     https:// if SOCIAL_AUTH_REDIRECT_IS_HTTPS is defined.
     """
     uri = self.request.build_absolute_uri(path)
     if setting('SOCIAL_AUTH_REDIRECT_IS_HTTPS'):
         uri = uri.replace('http://', 'https://')
     return uri
Пример #21
0
 def user_data(self, access_token, *args, **kwargs):
     """Loads user data from Orkut service"""
     fields = ORKUT_DEFAULT_DATA
     if setting('ORKUT_EXTRA_DATA'):
         fields += ',' + setting('ORKUT_EXTRA_DATA')
     scope = ORKUT_SCOPE + setting('ORKUT_EXTRA_SCOPE', [])
     params = {'method': 'people.get',
               'id': 'myself',
               'userId': '@me',
               'groupId': '@self',
               'fields': fields,
               'scope': ' '.join(scope)}
     request = self.oauth_request(access_token, ORKUT_REST_ENDPOINT, params)
     response = dsa_urlopen(request.to_url()).read()
     try:
         return simplejson.loads(response)['data']
     except (ValueError, KeyError):
         return None
Пример #22
0
 def user_data(self, access_token, *args, **kwargs):
     """Loads user data from Orkut service"""
     fields = ORKUT_DEFAULT_DATA
     if setting('ORKUT_EXTRA_DATA'):
         fields += ',' + setting('ORKUT_EXTRA_DATA')
     scope = ORKUT_SCOPE + setting('ORKUT_EXTRA_SCOPE', [])
     params = {
         'method': 'people.get',
         'id': 'myself',
         'userId': '@me',
         'groupId': '@self',
         'fields': fields,
         'scope': ' '.join(scope)
     }
     request = self.oauth_request(access_token, ORKUT_REST_ENDPOINT, params)
     response = dsa_urlopen(request.to_url()).read()
     try:
         return simplejson.loads(response)['data']
     except (ValueError, KeyError):
         return None
Пример #23
0
 def extra_data(self, user, uid, response, details):
     """Return users extra data"""
     # BrowserID sends timestamp for expiration date, here we
     # comvert it to the remaining seconds
     expires = (response['expires'] / 1000) - \
               time.mktime(datetime.now().timetuple())
     return {
         'audience': response['audience'],
         'issuer': response['issuer'],
         setting('SOCIAL_AUTH_EXPIRATION', 'expires'): expires
     }
Пример #24
0
 def user_data(self, access_token, *args, **kwargs):
     """Return user data provided"""
     fields_selectors = LINKEDIN_FIELD_SELECTORS + \
                        setting('LINKEDIN_EXTRA_FIELD_SELECTORS', [])
     url = LINKEDIN_CHECK_AUTH + ':(%s)' % ','.join(fields_selectors)
     request = self.oauth_request(access_token, url)
     raw_xml = self.fetch_response(request)
     try:
         return to_dict(ElementTree.fromstring(raw_xml))
     except (ExpatError, KeyError, IndexError):
         return None
Пример #25
0
 def user_data(self, access_token, *args, **kwargs):
     """Return user data provided"""
     fields_selectors = LINKEDIN_FIELD_SELECTORS + \
                        setting('LINKEDIN_EXTRA_FIELD_SELECTORS', [])
     url = LINKEDIN_CHECK_AUTH + ':(%s)' % ','.join(fields_selectors)
     request = self.oauth_request(access_token, url)
     raw_xml = self.fetch_response(request)
     try:
         return to_dict(ElementTree.fromstring(raw_xml))
     except (ExpatError, KeyError, IndexError):
         return None
Пример #26
0
 def extra_data(self, user, uid, response, details):
     """Return users extra data"""
     # BrowserID sends timestamp for expiration date, here we
     # comvert it to the remaining seconds
     expires = (response['expires'] / 1000) - \
               time.mktime(datetime.now().timetuple())
     return {
         'audience': response['audience'],
         'issuer': response['issuer'],
         setting('SOCIAL_AUTH_EXPIRATION', 'expires'): expires
     }
Пример #27
0
class VKontakteAuth(BaseAuth):
    """VKontakte OpenAPI authorization mechanism"""
    AUTH_BACKEND = VKontakteBackend
    APP_ID = setting('VKONTAKTE_APP_ID')

    def user_data(self, access_token, *args, **kwargs):
        return dict(self.request.GET)

    def auth_html(self):
        """Returns local VK authentication page, not necessary for
        VK to authenticate.
        """
        from django.template import RequestContext, loader

        dict = {'VK_APP_ID': self.APP_ID, 'VK_COMPLETE_URL': self.redirect}

        vk_template = loader.get_template(LOCAL_HTML)
        context = RequestContext(self.request, dict)

        return vk_template.render(context)

    def auth_complete(self, *args, **kwargs):
        """Performs check of authentication in VKontakte, returns User if
        succeeded"""
        app_cookie = 'vk_app_' + self.APP_ID

        if not 'id' in self.request.GET or \
           not app_cookie in self.request.COOKIES:
            raise ValueError('VKontakte authentication is not completed')

        cookie_dict = dict(
            item.split('=')
            for item in self.request.COOKIES[app_cookie].split('&'))
        check_str = ''.join(item + '=' + cookie_dict[item]
                            for item in ['expire', 'mid', 'secret', 'sid'])

        hash = md5(check_str + setting('VKONTAKTE_APP_SECRET')).hexdigest()

        if hash != cookie_dict['sig'] or int(cookie_dict['expire']) < time():
            raise ValueError('VKontakte authentication failed: invalid hash')
        else:
            kwargs.update({
                'auth': self,
                'response': self.user_data(cookie_dict['mid']),
                self.AUTH_BACKEND.name: True
            })
            return authenticate(*args, **kwargs)

    @property
    def uses_redirect(self):
        """VKontakte does not require visiting server url in order
        to do authentication, so auth_xxx methods are not needed to be called.
        Their current implementation is just an example"""
        return False
Пример #28
0
    def user_data(self, access_token, response, *args, **kwargs):
        """Loads user data from service"""
        fields = ','.join(VK_DEFAULT_DATA + setting('VK_EXTRA_DATA', []))
        params = {'access_token': access_token,
                  'fields': fields,
                  'uids': response.get('user_id')}

        data = vkontakte_api('users.get', params)

        if data:
            data = data.get('response')[0]
            data['user_photo'] = data.get('photo')  # Backward compatibility

        return data
Пример #29
0
class FlickrBackend(OAuthBackend):
    """Flickr OAuth authentication backend"""
    name = 'flickr'
    # Default extra data to store
    EXTRA_DATA = [('id', 'id'), ('username', 'username'),
                  ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))]

    def get_user_details(self, response):
        """Return user details from Flickr account"""
        return {
            USERNAME: response.get('id'),
            'email': '',
            'first_name': response.get('fullname')
        }
Пример #30
0
class GithubBackend(OAuthBackend):
    """Github OAuth authentication backend"""
    name = 'github'
    # Default extra data to store
    EXTRA_DATA = [
        ('id', 'id'),
        ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))
    ]

    def get_user_details(self, response):
        """Return user details from Github account"""
        return {USERNAME: response.get('login'),
                'email': response.get('email') or '',
                'first_name': response.get('name')}
Пример #31
0
def load_signed_request(signed_request, api_secret=None):
    try:
        sig, payload = signed_request.split(u".", 1)
        sig = base64_url_decode(sig)
        data = simplejson.loads(base64_url_decode(payload))

        expected_sig = hmac.new(
            api_secret or setting("FACEBOOK_API_SECRET"), msg=payload, digestmod=hashlib.sha256
        ).digest()

        # allow the signed_request to function for upto 1 day
        if sig == expected_sig and data[u"issued_at"] > (time.time() - 86400):
            return data
    except ValueError:
        pass  # ignore if can't split on dot
Пример #32
0
def update_user_details(backend,
                        details,
                        response,
                        user,
                        is_new=False,
                        *args,
                        **kwargs):
    """Update user details using data from provider."""
    changed = False  # flag to track changes

    for name, value in details.iteritems():
        # do not update username, it was already generated
        # do not update configured fields if user already existed
        if name in (USERNAME, 'id', 'pk') or (not is_new and name in setting(
                'SOCIAL_AUTH_PROTECTED_USER_FIELDS', [])):
            continue
        if value and value != getattr(user, name, None):
            setattr(user, name, value)
            changed = True

    # Fire a pre-update signal sending current backend instance,
    # user instance (created or retrieved from database), service
    # response and processed details.
    #
    # Also fire socialauth_registered signal for newly registered
    # users.
    #
    # Signal handlers must return True or False to signal instance
    # changes. Send method returns a list of tuples with receiver
    # and it's response.
    signal_response = lambda (receiver, response): response
    signal_kwargs = {
        'sender': backend.__class__,
        'user': user,
        'response': response,
        'details': details
    }

    changed |= any(filter(signal_response, pre_update.send(**signal_kwargs)))

    # Fire socialauth_registered signal on new user registration
    if is_new:
        changed |= any(
            filter(signal_response,
                   socialauth_registered.send(**signal_kwargs)))

    if changed:
        user.save()
Пример #33
0
def load_signed_request(signed_request, api_secret=None):
    try:
        sig, payload = signed_request.split(u'.', 1)
        sig = base64_url_decode(sig)
        data = simplejson.loads(base64_url_decode(payload))

        expected_sig = hmac.new(api_secret or setting('FACEBOOK_API_SECRET'),
                                msg=payload,
                                digestmod=hashlib.sha256).digest()

        # allow the signed_request to function for upto 1 day
        if sig == expected_sig and \
                data[u'issued_at'] > (time.time() - 86400):
            return data
    except ValueError:
        pass  # ignore if can't split on dot
Пример #34
0
    def user_data(self, access_token, response, *args, **kwargs):
        """Loads user data from service"""
        fields = ','.join(VK_DEFAULT_DATA + setting('VK_EXTRA_DATA', []))
        params = {
            'access_token': access_token,
            'fields': fields,
            'uids': response.get('user_id')
        }

        data = vkontakte_api('users.get', params)

        if data:
            data = data.get('response')[0]
            data['user_photo'] = data.get('photo')  # Backward compatibility

        return data
Пример #35
0
def auth_process(request, backend):
    """Authenticate using social backend"""
    # Save any defined next value into session
    data = request.POST if request.method == 'POST' else request.GET
    if REDIRECT_FIELD_NAME in data:
        # Check and sanitize a user-defined GET/POST next field value
        redirect = data[REDIRECT_FIELD_NAME]
        if setting('SOCIAL_AUTH_SANITIZE_REDIRECTS', True):
            redirect = sanitize_redirect(request.get_host(), redirect)
        request.session[REDIRECT_FIELD_NAME] = redirect or DEFAULT_REDIRECT

    # Clean any partial pipeline info before starting the process
    clean_partial_pipeline(request)

    if backend.uses_redirect:
        return HttpResponseRedirect(backend.auth_url())
    else:
        return HttpResponse(backend.auth_html(),
                            content_type='text/html;charset=UTF-8')
Пример #36
0
class DropboxBackend(OAuthBackend):
    """Dropbox OAuth authentication backend"""
    name = 'dropbox'
    # Default extra data to store
    EXTRA_DATA = [('id', 'id'),
                  ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))]

    def get_user_details(self, response):
        """Return user details from Dropbox account"""
        return {
            USERNAME: str(response.get('uid')),
            'email': response.get('email'),
            'first_name': response.get('display_name')
        }

    def get_user_id(self, details, response):
        """OAuth providers return an unique user id in response"""
        # Dropbox uses a uid parameter instead of id like most others...
        return response['uid']
Пример #37
0
class VKontakteOAuth2Backend(OAuthBackend):
    """VKontakteOAuth2 authentication backend"""
    name = 'vkontakte-oauth2'

    EXTRA_DATA = [('id', 'id'),
                  ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))]

    def get_user_id(self, details, response):
        """OAuth providers return an unique user id in response"""
        return response['user_id']

    def get_user_details(self, response):
        """Return user details from Vkontakte account"""
        return {
            USERNAME: response.get('screen_name'),
            'email': '',
            'first_name': response.get('first_name'),
            'last_name': response.get('last_name')
        }
Пример #38
0
def auth_process(request, backend):
    """Authenticate using social backend"""
    # Save any defined next value into session
    data = request.POST if request.method == 'POST' else request.GET
    if REDIRECT_FIELD_NAME in data:
        # Check and sanitize a user-defined GET/POST next field value
        redirect = data[REDIRECT_FIELD_NAME]
        if setting('SOCIAL_AUTH_SANITIZE_REDIRECTS', True):
            redirect = sanitize_redirect(request.get_host(), redirect)
        request.session[REDIRECT_FIELD_NAME] = redirect or DEFAULT_REDIRECT

    # Clean any partial pipeline info before starting the process
    clean_partial_pipeline(request)

    if backend.uses_redirect:
        return HttpResponseRedirect(backend.auth_url())
    else:
        return HttpResponse(backend.auth_html(),
                            content_type='text/html;charset=UTF-8')
Пример #39
0
class BitbucketBackend(OAuthBackend):
    """Bitbucket OAuth authentication backend"""
    name = 'bitbucket'
    EXTRA_DATA = [('username', 'username'),
                  ('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires')),
                  ('email', 'email'), ('first_name', 'first_name'),
                  ('last_name', 'last_name')]

    def get_user_details(self, response):
        """Return user details from Bitbucket account"""
        return {
            USERNAME:
            response.get('username'),
            'email':
            response.get('email'),
            'fullname':
            ' '.join((response.get('first_name'), response.get('last_name'))),
            'first_name':
            response.get('first_name'),
            'last_name':
            response.get('last_name')
        }

    def get_user_id(self, details, response):
        """Return the user id, Bitbucket only provides username as a unique
        identifier"""
        return response['username']

    @classmethod
    def tokens(cls, instance):
        """Return the tokens needed to authenticate the access to any API the
        service might provide. Bitbucket uses a pair of OAuthToken consisting
        on a oauth_token and oauth_token_secret.

        instance must be a UserSocialAuth instance.
        """
        token = super(BitbucketBackend, cls).tokens(instance)
        if token and 'access_token' in token:
            token = dict(
                tok.split('=') for tok in token['access_token'].split('&'))
        return token
Пример #40
0
    def extra_data(self, user, uid, response, details):
        """Return access_token and extra defined names to store in
        extra_data field"""
        data = {'access_token': response.get('access_token', '')}
        name = self.name.replace('-', '_').upper()
        names = (self.EXTRA_DATA or []) + setting(name + '_EXTRA_DATA', [])
        for entry in names:
            if len(entry) == 2:
                (name, alias), discard = entry, False
            elif len(entry) == 3:
                name, alias, discard = entry
            elif len(entry) == 1:
                name = alias = entry
            else:  # ???
                continue

            value = response.get(name)
            if discard and not value:
                continue
            data[alias] = value
        return data
Пример #41
0
def update_user_details(backend, details, response, user, is_new=False, *args,
                        **kwargs):
    """Update user details using data from provider."""
    changed = False  # flag to track changes

    for name, value in details.iteritems():
        # do not update username, it was already generated
        # do not update configured fields if user already existed
        if name in (USERNAME, 'id', 'pk') or (not is_new and
            name in setting('SOCIAL_AUTH_PROTECTED_USER_FIELDS', [])):
            continue
        if value and value != getattr(user, name, None):
            setattr(user, name, value)
            changed = True

    # Fire a pre-update signal sending current backend instance,
    # user instance (created or retrieved from database), service
    # response and processed details.
    #
    # Also fire socialauth_registered signal for newly registered
    # users.
    #
    # Signal handlers must return True or False to signal instance
    # changes. Send method returns a list of tuples with receiver
    # and it's response.
    signal_response = lambda (receiver, response): response
    signal_kwargs = {'sender': backend.__class__, 'user': user,
                     'response': response, 'details': details}

    changed |= any(filter(signal_response, pre_update.send(**signal_kwargs)))

    # Fire socialauth_registered signal on new user registration
    if is_new:
        changed |= any(filter(signal_response,
                              socialauth_registered.send(**signal_kwargs)))

    if changed:
        user.save()
Пример #42
0
class GoogleOAuth2Backend(GoogleOAuthBackend):
    """Google OAuth2 authentication backend"""
    name = 'google-oauth2'
    EXTRA_DATA = [('refresh_token', 'refresh_token', True),
                  ('expires_in', setting('SOCIAL_AUTH_EXPIRATION', 'expires'))]

    def get_user_id(self, details, response):
        """Use google email or id as unique id"""
        user_id = super(GoogleOAuth2Backend,
                        self).get_user_id(details, response)
        if setting('GOOGLE_OAUTH2_USE_UNIQUE_USER_ID', False):
            return response['id']
        return user_id

    def get_user_details(self, response):
        email = response.get('email', '')
        return {
            USERNAME: email.split('@', 1)[0],
            'email': email,
            'fullname': response.get('name', ''),
            'first_name': response.get('given_name', ''),
            'last_name': response.get('family_name', '')
        }
Пример #43
0
                                 BaseOAuth2, USERNAME
from core.social_auth.utils import setting, log, dsa_urlopen


# Vkontakte configuration
VK_AUTHORIZATION_URL = 'http://oauth.vk.com/authorize'
VK_ACCESS_TOKEN_URL = 'https://oauth.vk.com/access_token'
VK_SERVER = 'vk.com'
VK_DEFAULT_DATA = ['first_name', 'last_name', 'screen_name',
                   'nickname', 'photo']

VKONTAKTE_API_URL = 'https://api.vkontakte.ru/method/'
VKONTAKTE_SERVER_API_URL = 'http://api.vkontakte.ru/api.php'
VKONTAKTE_API_VERSION = '3.0'

USE_APP_AUTH = setting('VKONTAKTE_APP_AUTH', False)
LOCAL_HTML = setting('VKONTAKTE_LOCAL_HTML', 'vkontakte.html')


class VKontakteBackend(SocialAuthBackend):
    """VKontakte OpenAPI authentication backend"""
    name = 'vkontakte'

    def get_user_id(self, details, response):
        """Return user unique id provided by VKontakte"""
        return response['id']

    def get_user_details(self, response):
        """Return user details from VKontakte request"""
        nickname = response.get('nickname') or ''
        return {
Пример #44
0
from core.social_auth.db.base import UserSocialAuthMixin, AssociationMixin, \
                                NonceMixin
from core.social_auth.fields import JSONField
from core.social_auth.utils import setting
from django.contrib.auth.models import User

# If User class is overridden, it *must* provide the following fields
# and methods work with django-social-auth:
#
#   username   = CharField()
#   last_login = DateTimeField()
#   is_active  = BooleanField()
#   def is_authenticated():
#       ...
if setting('SOCIAL_AUTH_USER_MODEL'):
    UserModel = models.get_model(*setting('SOCIAL_AUTH_USER_MODEL')
                                    .rsplit('.', 1))
else:
    from django.contrib.auth.models import User as UserModel


class UserSocialAuth(models.Model, UserSocialAuthMixin):
    """Social Auth association model"""
    User = UserModel
    user = models.ForeignKey(UserModel, related_name='social_auth')
    provider = models.CharField(max_length=32)
    uid = models.CharField(max_length=255)
    extra_data = JSONField(default='{}')

    class Meta:
Пример #45
0
"""

import os.path, urllib2, core

from django.http import HttpResponseRedirect, HttpResponse
from django.contrib.auth import login, REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.views.decorators.csrf import csrf_exempt

from core.social_auth.utils import sanitize_redirect, setting, \
                              backend_setting, clean_partial_pipeline
from core.social_auth.decorators import dsa_view


DEFAULT_REDIRECT = setting('SOCIAL_AUTH_LOGIN_REDIRECT_URL') or \
                   setting('LOGIN_REDIRECT_URL')
LOGIN_ERROR_URL = setting('LOGIN_ERROR_URL', setting('LOGIN_URL'))
PIPELINE_KEY = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline')


@dsa_view(setting('SOCIAL_AUTH_COMPLETE_URL_NAME', 'socialauth_complete'))
def auth(request, backend):
    """Start authentication process"""
    return auth_process(request, backend)


@csrf_exempt
@dsa_view()
def complete(request, backend, *args, **kwargs):
    """Authentication complete view, override this view if transaction
Пример #46
0
            return super(GoogleOAuth, cls).get_key_and_secret()
        except AttributeError:
            return 'anonymous', 'anonymous'

    @classmethod
    def enabled(cls):
        """Google OAuth is always enabled because of anonymous access"""
        return True

    def registered(self):
        """Check if Google OAuth Consumer Key and Consumer Secret are set"""
        return self.get_key_and_secret() != ('anonymous', 'anonymous')


# TODO: Remove this setting name check, keep for backward compatibility
_OAUTH2_KEY_NAME = setting('GOOGLE_OAUTH2_CLIENT_ID') and \
                   'GOOGLE_OAUTH2_CLIENT_ID' or \
                   'GOOGLE_OAUTH2_CLIENT_KEY'


class GoogleOAuth2(BaseOAuth2):
    """Google OAuth2 support"""
    AUTH_BACKEND = GoogleOAuth2Backend
    AUTHORIZATION_URL = 'https://accounts.google.com/o/oauth2/auth'
    ACCESS_TOKEN_URL = 'https://accounts.google.com/o/oauth2/token'
    SETTINGS_KEY_NAME = _OAUTH2_KEY_NAME
    SETTINGS_SECRET_NAME = 'GOOGLE_OAUTH2_CLIENT_SECRET'
    SCOPE_VAR_NAME = 'GOOGLE_OAUTH_EXTRA_SCOPE'
    DEFAULT_SCOPE = GOOGLE_OAUTH2_SCOPE
    REDIRECT_STATE = False
Пример #47
0
def complete_process(request, backend, *args, **kwargs):
    """Authentication complete process"""
    # pop redirect value before the session is trashed on login()
    redirect_value = request.session.get(REDIRECT_FIELD_NAME, '')
    user = auth_complete(request, backend, *args, **kwargs)

    if isinstance(user, HttpResponse):
        return user

    if not user and request.user.is_authenticated():
        return HttpResponseRedirect(redirect_value)

    if user:
        # copy the profile image
        if user.social_user.provider == 'facebook':
          picture_page = "https://graph.facebook.com/"+user.username+"/picture?type=square"
          
        if user.social_user.provider == 'twitter':
          picture_page = "http://api.twitter.com/1/users/profile_image?screen_name="+user.username+"&size=normal"
        
        if user.social_user.provider == 'yahoo':
          picture_page = "http://img.msg.yahoo.com/avatar.php?yids="+user.username
        
        if user.social_user.provider == 'google':
          picture_page = None
        
        if picture_page:
            opener1 = urllib2.build_opener()
            page1 = opener1.open(picture_page)
            my_picture = page1.read()
            filename = core.__path__[0] + '/static/photos/profile/'+ user.username
            fout = open(filename, "wb")
            fout.write(my_picture)
            fout.close()
        
        if getattr(user, 'is_active', True):
            # catch is_new flag before login() might reset the instance
            is_new = getattr(user, 'is_new', False)
            login(request, user)
            # user.social_user is the used UserSocialAuth instance defined
            # in authenticate process
            social_user = user.social_user
            if redirect_value:
                request.session[REDIRECT_FIELD_NAME] = redirect_value or \
                                                       DEFAULT_REDIRECT

            if setting('SOCIAL_AUTH_SESSION_EXPIRATION', True):
                # Set session expiration date if present and not disabled by
                # setting. Use last social-auth instance for current provider,
                # users can associate several accounts with a same provider.
                expiration = social_user.expiration_datetime()
                if expiration:
                    try:
                        request.session.set_expiry(expiration)
                    except OverflowError:
                        # Handle django time zone overflow, set default expiry.
                        request.session.set_expiry(None)

            # store last login backend name in session
            key = setting('SOCIAL_AUTH_LAST_LOGIN',
                          'social_auth_last_login_backend')
            request.session[key] = social_user.provider

            # Remove possible redirect URL from session, if this is a new
            # account, send him to the new-users-page if defined.
            new_user_redirect = backend_setting(backend,
                                           'SOCIAL_AUTH_NEW_USER_REDIRECT_URL')
            if new_user_redirect and is_new:
                url = new_user_redirect
            else:
                url = redirect_value or \
                      backend_setting(backend,
                                      'SOCIAL_AUTH_LOGIN_REDIRECT_URL') or \
                      DEFAULT_REDIRECT
        else:
            url = backend_setting(backend, 'SOCIAL_AUTH_INACTIVE_USER_URL',
                                  LOGIN_ERROR_URL)
    else:
        msg = setting('LOGIN_ERROR_MESSAGE', None)
        if msg:
            messages.error(request, msg)
        url = backend_setting(backend, 'LOGIN_ERROR_URL', LOGIN_ERROR_URL)
    return HttpResponse("<script type='text/javascript'> window.close(); window.opener.refreshPage(); </script>");
Пример #48
0
 def get_scope(self):
     return setting(VKontakteOAuth2.SCOPE_VAR_NAME) or \
            setting('VKONTAKTE_OAUTH2_EXTRA_SCOPE')
Пример #49
0
def _api_get_val_fun(name, conf):
    if USE_APP_AUTH:
        return USE_APP_AUTH.get(name)
    else:
        return setting(conf)
Пример #50
0
from functools import wraps

from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, HttpResponseServerError
from django.utils.importlib import import_module

from core.social_auth.backends import get_backend
from core.social_auth.utils import setting, log, backend_setting


LOGIN_ERROR_URL = setting("LOGIN_ERROR_URL", setting("LOGIN_URL"))
PROCESS_EXCEPTIONS = setting("SOCIAL_AUTH_PROCESS_EXCEPTIONS", "core.social_auth.utils.log_exceptions_to_messages")


def dsa_view(redirect_name=None):
    """Decorate djangos-social-auth views. Will check and retrieve backend
    or return HttpResponseServerError if backend is not found.

        redirect_name parameter is used to build redirect URL used by backend.
    """

    def dec(func):
        @wraps(func)
        def wrapper(request, backend, *args, **kwargs):
            if redirect_name:
                redirect = reverse(redirect_name, args=(backend,))
            else:
                redirect = request.path
            backend = get_backend(backend, request, redirect)

            if not backend:
Пример #51
0
        def wrapper(request, backend, *args, **kwargs):
            if redirect_name:
                redirect = reverse(redirect_name, args=(backend,))
            else:
                redirect = request.path
            backend = get_backend(backend, request, redirect)

            if not backend:
                return HttpResponseServerError("Incorrect authentication " + "service")

            RAISE_EXCEPTIONS = backend_setting(backend, "SOCIAL_AUTH_RAISE_EXCEPTIONS", setting("DEBUG"))
            try:
                return func(request, backend, *args, **kwargs)
            except Exception, e:  # some error ocurred
                if RAISE_EXCEPTIONS:
                    raise
                log("error", unicode(e), exc_info=True, extra={"request": request})

                url = None
                mod, func_name = PROCESS_EXCEPTIONS.rsplit(".", 1)
                try:
                    process = getattr(import_module(mod), func_name, lambda *args: None)
                except ImportError:
                    pass
                else:
                    url = process(request, backend, e)

                if not url:
                    url = backend_setting(backend, "SOCIAL_AUTH_BACKEND_ERROR_URL", LOGIN_ERROR_URL)
                return HttpResponseRedirect(url)
Пример #52
0
"""
from urllib2 import HTTPError
try:
    from urlparse import parse_qs
    parse_qs  # placate pyflakes
except ImportError:
    # fall back for Python 2.5
    from cgi import parse_qs

from oauth2 import Token
from core.social_auth.utils import setting
from core.social_auth.backends import ConsumerBasedOAuth, OAuthBackend, USERNAME, \
                                 exceptions


if setting('EVERNOTE_DEBUG', False):
    EVERNOTE_SERVER = 'sandbox.evernote.com'
else:
    EVERNOTE_SERVER = 'www.evernote.com'

EVERNOTE_REQUEST_TOKEN_URL = 'https://%s/oauth' % EVERNOTE_SERVER
EVERNOTE_ACCESS_TOKEN_URL = 'https://%s/oauth' % EVERNOTE_SERVER
EVERNOTE_AUTHORIZATION_URL = 'https://%s/OAuth.action' % EVERNOTE_SERVER


class EvernoteBackend(OAuthBackend):
    """
    Evernote OAuth authentication backend.

    Possible Values:
       {'edam_expires': ['1367525289541'],
Пример #53
0
 def enabled(cls):
     """Return backend enabled status by checking basic settings"""
     return setting('DROPBOX_APP_ID') and setting('DROPBOX_API_SECRET')