Beispiel #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)
Beispiel #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)
Beispiel #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
Beispiel #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')
Beispiel #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')
Beispiel #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}
Beispiel #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
Beispiel #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', {})
Beispiel #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', {})
Beispiel #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,
        }
Beispiel #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
Beispiel #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']
Beispiel #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)
Beispiel #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)
Beispiel #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)
Beispiel #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
Beispiel #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
Beispiel #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')
        }
Beispiel #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)
Beispiel #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
Beispiel #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
Beispiel #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
Beispiel #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
     }
Beispiel #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
Beispiel #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
Beispiel #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
     }
Beispiel #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
Beispiel #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
Beispiel #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')
        }
Beispiel #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')}
Beispiel #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
Beispiel #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()
Beispiel #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
Beispiel #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
Beispiel #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')
Beispiel #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']
Beispiel #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')
        }
Beispiel #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')
Beispiel #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
Beispiel #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
Beispiel #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()
Beispiel #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', '')
        }
Beispiel #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 {
Beispiel #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:
Beispiel #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
Beispiel #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
Beispiel #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>");
Beispiel #48
0
 def get_scope(self):
     return setting(VKontakteOAuth2.SCOPE_VAR_NAME) or \
            setting('VKONTAKTE_OAUTH2_EXTRA_SCOPE')
Beispiel #49
0
def _api_get_val_fun(name, conf):
    if USE_APP_AUTH:
        return USE_APP_AUTH.get(name)
    else:
        return setting(conf)
Beispiel #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:
Beispiel #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)
Beispiel #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'],
Beispiel #53
0
 def enabled(cls):
     """Return backend enabled status by checking basic settings"""
     return setting('DROPBOX_APP_ID') and setting('DROPBOX_API_SECRET')