Example #1
0
def facebook_login(request, redirect_field_name="next",
                        redirect_to_session_key="redirect_to",
                        display="page"):
    """
        1. access OAuth
        2. set token to none
        3. store and redirect to authorization url
        4. redirect to OAuth authorization url
    """
    
    access = OAuthAccess()
    token = None
    if hasattr(request, "session"):
        logger.debug("la_facebook.views.facebook_login: request has session")
        # this session variable is used by the callback
        request.session[redirect_to_session_key] = request.GET.get(redirect_field_name)
    if request.method == "POST":
        data = parse_signed_request(request.POST['signed_request'], settings.FACEBOOK_APP_SECRET)
        facebookid = data['user_id']
        user_id = UserAssociation.objects.get(identifier=facebookid).user_id
        profile = Profile.objects.get(user_id=user_id)
        profile.single = bool(data['registration']['single'])


    return HttpResponseRedirect(access.authorization_url(token, display=display))
Example #2
0
    def __call__(self, request, access, token):
        if not request.user.is_authenticated():
            logger.debug("BaseFacebookCallback.__call__:'\
                    ' request.user not authenticated")
            self.authenticated = False
            user_data = self.fetch_user_data(request, access, token)
            user = self.lookup_user(request, access, user_data)
            if user is None:
                logger.debug("BaseFacebookCallback.__call__:'\
                 ' no existing django user found for this facebook identifier")
                ret = self.handle_no_user(request, access, token, user_data)
                # allow handle_no_user to create a user if need be
                if isinstance(ret, User):
                    logger.debug("BaseFacebookCallback.__call__:'\
                            self.handle_no_user returned valid django user")
                    user = ret
            else:
                logger.debug("BaseFacebookCallback.__call__:'\
                   existing django user found for this facebook identifier")
                ret = self.handle_unauthenticated_user(request, user, access, 
                        token, user_data)
            if isinstance(ret, HttpResponse):
                return ret
        else:
            logger.debug("BaseFacebookCallback.__call__:'\
                    request.user is authenticated")
            self.authenticated = True
            user = request.user
        redirect_to = self.redirect_url(request)

        return redirect(redirect_to)
Example #3
0
 def authorized_token(self, token, verifier=None):
     """
         authorize token
         verify OAuth
         set OAuth client
         post OAuth content
         response not 200 raise unknown response
         return OAuth token as string
     """
     parameters = {}
     if verifier:
         parameters.update({
             "oauth_verifier": verifier,
         })
     client = oauth.Client(self.consumer, token=token)
     logger.debug("OAuthAccess.authorized_token: params: %s" % parameters)
     response, content = client.request(
         self.access_token_url,
         method="POST",
         # parameters must be urlencoded (which are then re-decoded by
         # oauth2 -- seems lame)
         body=urllib.urlencode(parameters),
     )
     if response["status"] != "200":
         raise UnknownResponse(
             "Got %s from %s:\n\n%s" %
             (response["status"], self.access_token_url, content))
     logger.debug("OAuthAccess.authorized_token: response from %s: %s" %
                  (self.access_token_url, content))
     return oauth.Token.from_string(content)
Example #4
0
    def create_user(self, request, access, token, user_data):
        identifier = self.identifier_from_data(user_data)
        username = hashlib.sha224(str(identifier)).hexdigest()[:30]
        if User.objects.filter(username=username).count():
            logger.warning("DefaultFacebookCallback.create_user: A user for" \
                    "was already found, when asked to create a user for %s"
                    % username)
            user = User.objects.get(username=username)
        else:
            user = User(username=username)
            user.set_unusable_password()
            logger.debug(user_data)
            if 'email' in user_data:
                user.email = user_data["email"]
            if 'first_name' in user_data:
                user.first_name = user_data['first_name']
            if 'last_name' in user_data:
                user.last_name = user_data['last_name']
            user.save()
            logger.debug("DefaultFacebookCallback.create_user: new django" \
                    "user created for %s" % username)

        self.create_profile(request, access, token, user)
        self.handle_unauthenticated_user(request, user ,access, token, user_data)
        return user
Example #5
0
    def redirect_url(self, request, fallback_url=settings.LOGIN_REDIRECT_URL, 
            redirect_field_name="next", session_key_value="redirect_to"):
        """
        Returns the URL to be used in login procedures by looking at different
        values in the following order:

        - a REQUEST value, GET or POST, named "next" by default.
        - LOGIN_REDIRECT_URL - the URL in the setting
        - LOGIN_REDIRECT_URLNAME - the name of a URLconf entry in the settings
        """

        redirect_to = request.REQUEST.get(redirect_field_name)
        if not redirect_to:
            logger.debug("redirect not in get params")
            # try the session if available
            if hasattr(request, "session"):
                redirect_to = request.session.get(session_key_value)
                # Heavier security check -- don't allow redirection to a different host.
                netloc = urlparse.urlparse(redirect_to)[1]
                if netloc and netloc != request.host:
                    logger.warning("redirect_to host does not match orgin")
                    redirect_to = fallback_url
        if not redirect_to:
            logger.debug("no redirect found, using fallback")
            redirect_to = fallback_url
        return redirect_to
Example #6
0
 def update_profile(self, user_data, profile):
     for k, v in user_data.items():
         if k !='id' and hasattr(profile, k):
             setattr(profile, k, v)
             logger.debug("DefaultFacebookCallback.update_profile_from_graph"\
                     ": updating profile %s to %s" % (k,v))
     return profile
 def update_profile_from_graph(self, request, access, token, profile):
     user_data = self.fetch_user_data(request, access, token)
     for k, v in user_data.items():
         if k != 'id' and hasattr(profile, k):
             setattr(profile, k, v)
             logger.debug("DefaultFacebookCallback.update_profile_from_graph: updating profile %s to %s" % (k, v))
     return profile
Example #8
0
 def update_profile(self, user_data, profile):
     for k, v in user_data.items():
         if k != 'id' and hasattr(profile, k):
             setattr(profile, k, v)
             logger.debug("DefaultFacebookCallback.update_profile_from_graph"\
                     ": updating profile %s to %s" % (k,v))
     return profile
Example #9
0
def get_friends_on_site(user):
    """ Find FB friends that are also using the site. """
    try:
        get_friends_internally = FACEBOOK_SETTINGS['STORE_FRIENDS']
    except KeyError:
        get_friends_internally = False

    if get_friends_internally:
        logger.debug('Getting friends internally for {0}'.format(user))
        friend_ids_on_site = Friend.objects.filter(uid1=user).values_list(
            'uid2', flat=True)
        friend_user_associations = UserAssociation.objects.filter(
            user__pk__in=friend_ids_on_site).all()
        return friend_user_associations
    else:
        logger.debug('Getting friends from Facebook for {0}'.format(user))
        # going to FB for friendships.
        fb_friends = get_friends_on_facebook(user)
        if fb_friends:
            # even though the FQL query says that we should only have user id's that
            # are associated with our app, we're still going to filter against our
            # data in case there is some breakage (FB has them but we don't)
            site_friends = UserAssociation.objects.filter(
                identifier__in=[i['uid'] for i in fb_friends])
            return site_friends
    return []
 def authorized_token(self, token, verifier=None):
     """
         authorize token
         verify OAuth
         set OAuth client
         post OAuth content
         response not 200 raise unknown response
         return OAuth token as string
     """
     parameters = {}
     if verifier:
         parameters.update({"oauth_verifier": verifier})
     client = oauth.Client(self.consumer, token=token)
     logger.debug("OAuthAccess.authorized_token: params: %s" % parameters)
     response, content = client.request(
         self.access_token_url,
         method="POST",
         # parameters must be urlencoded (which are then re-decoded by
         # oauth2 -- seems lame)
         body=urllib.urlencode(parameters),
     )
     if response["status"] != "200":
         raise UnknownResponse("Got %s from %s:\n\n%s" % (response["status"], self.access_token_url, content))
     logger.debug("OAuthAccess.authorized_token: response from %s: %s" % (self.access_token_url, content))
     return oauth.Token.from_string(content)
 def make_api_call(self, kind, url, token, method="GET", **kwargs):
     if isinstance(token, OAuth20Token):
         request_kwargs = dict(method=method)
         if method == "POST":
             params = {"access_token": str(token)}
             params.update(kwargs["params"])
             request_kwargs["body"] = urllib.urlencode(params)
         else:
             url += "?%s" % urllib.urlencode(dict(access_token=str(token)))
         http = httplib2.Http()
         response, content = http.request(url, **request_kwargs)
     else:
         raise ValueError("an OAuth20Token is required for API call")
     if response["status"] == "401":
         raise NotAuthorized()
     if not content:
         raise ServiceFail("no content")
     logger.debug("OAuthAccess.make_api_call: content returned: %r" % content)
     if kind == "raw":
         return content
     elif kind == "json":
         try:
             return json.loads(content)
         except ValueError:
             # @@@ might be better to return a uniform cannot parse
             # exception and let caller determine if it is service fail
             raise ServiceFail("JSON parse error")
     elif kind == "xml":
         return etree.ElementTree(etree.fromstring(content))
     else:
         raise Exception("unsupported API kind")
Example #12
0
    def redirect_url(self, request, fallback_url=settings.LOGIN_REDIRECT_URL, 
            redirect_field_name="next", session_key_value="redirect_to"):
        """
        Returns the URL to be used in login procedures by looking at different
        values in the following order:

        - a REQUEST value, GET or POST, named "next" by default.
        - LOGIN_REDIRECT_URL - the URL in the setting
        - LOGIN_REDIRECT_URLNAME - the name of a URLconf entry in the settings
        """

        #modified by Jeff. For some reason this is causing a login error so I just redirect to settings.LOGIN_REDIRECT_URL immediately
        # redirect_to = request.REQUEST.get(redirect_field_name)
        redirect_to = settings.LOGIN_REDIRECT_URL
        if not redirect_to:
            logger.debug("redirect not in get params")
            # try the session if available
            if hasattr(request, "session"):
                redirect_to = request.session.get(session_key_value)
                # Heavier security check -- don't allow redirection to a different host.
                netloc = urlparse.urlparse(redirect_to)[1]
                if netloc and netloc != request.host:
                    logger.warning("redirect_to host does not match orgin")
                    redirect_to = fallback_url
        if not redirect_to:
            logger.debug("no redirect found, using fallback")
            redirect_to = fallback_url
        return redirect_to
Example #13
0
def facebook_login(request,
                   redirect_field_name="next",
                   redirect_to_session_key="redirect_to",
                   display="page"):
    """
        1. access OAuth
        2. set token to none
        3. store and redirect to authorization url
        4. redirect to OAuth authorization url
    """

    access = OAuthAccess()
    token = None
    if hasattr(request, "session"):
        logger.debug("la_facebook.views.facebook_login: request has session")
        # this session variable is used by the callback
        request.session[redirect_to_session_key] = request.GET.get(
            redirect_field_name)
    if request.method == "POST":
        data = parse_signed_request(request.POST['signed_request'],
                                    settings.FACEBOOK_APP_SECRET)
        facebookid = data['user_id']
        user_id = UserAssociation.objects.get(identifier=facebookid).user_id
        profile = Profile.objects.get(user_id=user_id)
        profile.single = bool(data['registration']['single'])

    return HttpResponseRedirect(
        access.authorization_url(token, display=display))
Example #14
0
 def make_api_call(self, kind, url, token, method="GET", **kwargs):
     if isinstance(token, OAuth20Token):
         request_kwargs = dict(method=method)
         if method == "POST":
             params = {
                 "access_token": str(token),
             }
             params.update(kwargs["params"])
             request_kwargs["body"] = urllib.urlencode(params)
         else:
             url += "?%s" % urllib.urlencode(dict(access_token=str(token)))
         http = httplib2.Http()
         response, content = http.request(url, **request_kwargs)
     else:
         raise ValueError("an OAuth20Token is required for API call")
     if response["status"] == "401":
         raise NotAuthorized()
     if not content:
         raise ServiceFail("no content")
     logger.debug("OAuthAccess.make_api_call: content returned: %r" %
                  content)
     if kind == "raw":
         return content
     elif kind == "json":
         try:
             return json.loads(content)
         except ValueError:
             # @@@ might be better to return a uniform cannot parse
             # exception and let caller determine if it is service fail
             raise ServiceFail("JSON parse error")
     elif kind == "xml":
         return etree.ElementTree(etree.fromstring(content))
     else:
         raise Exception("unsupported API kind")
 def handle_unauthenticated_user(self, request, user, access, token, user_data):
     self.login_user(request, user)
     self.persist(user, token, user_data)
     # set session expiration to match token
     if token.expires:
         logger.debug("DefaultFacebookCallback.handle_unauthenticated_user: setting session expiration to: %s" % token.expires)
         seconds_to_expiry = (datetime.now() - token.expires).seconds
         request.session.set_expiry(seconds_to_expiry)
Example #16
0
 def update_profile_from_graph(self, request, access, token, profile):
     user_data = self.fetch_user_data(request, access, token)
     for k, v in user_data.items():
         if k != 'id' and hasattr(profile, k):
             setattr(profile, k, v)
             logger.debug("DefaultFacebookCallback.update_profile_from_graph"\
                     ": updating profile %s to %s" % (k,v))
     return profile
Example #17
0
 def handle_unauthenticated_user(self, request, user, access, token, user_data):
     self.login_user(request, user)
     identifier = self.identifier_from_data(user_data)
     self.persist(user, token, user_data)
     # set session expiration to match token
     if token.expires:
         logger.debug("DefaultFacebookCallback.handle_unauthenticated_user"\
                 ": setting session expiration to: %s" % token.expires)
         request.session.set_expiry(token.expires)
Example #18
0
 def handle_unauthenticated_user(self, request, user, access, token,
                                 user_data):
     self.login_user(request, user)
     identifier = self.identifier_from_data(user_data)
     self.persist(user, token, user_data)
     # set session expiration to match token
     if token.expires:
         logger.debug("DefaultFacebookCallback.handle_unauthenticated_user"\
                 ": setting session expiration to: %s" % token.expires)
         request.session.set_expiry(token.expires)
Example #19
0
def get_friends_on_facebook(user):
    """
    Go to Facebook to find a user's friends that have registered with the app.
    """
    try:
        assoc = UserAssociation.objects.get(user=user)
    except UserAssociation.DoesNotExist:
        logger.debug('No UserAssociation for {0}'.format(user))
        return None
    
    fql_query = "SELECT uid FROM user WHERE is_app_user AND uid IN (SELECT uid2 FROM friend WHERE uid1 = {0})".format(assoc.identifier)
    fb_friends = json.load(do_fql_query(fql_query, assoc.token))
    if 'error_code' not in fb_friends:
        return fb_friends
    return []
Example #20
0
def facebook_login(request, redirect_field_name="next",
                        redirect_to_session_key="redirect_to"):
    """
        1. access OAuth
        2. set token to none
        3. store and redirect to authorization url
        4. redirect to OAuth authorization url
    """
    
    access = OAuthAccess()
    token = None
    if hasattr(request, "session"):
        logger.debug("la_facebook.views.facebook_login: request has session")
        request.session[redirect_to_session_key] = request.GET.get(redirect_field_name)
    return HttpResponseRedirect(access.authorization_url(token))
Example #21
0
def get_friends_on_facebook(user):
    """
    Go to Facebook to find a user's friends that have registered with the app.
    """
    try:
        assoc = UserAssociation.objects.get(user=user)
    except UserAssociation.DoesNotExist:
        logger.debug('No UserAssociation for {0}'.format(user))
        return None

    fql_query = "SELECT uid FROM user WHERE is_app_user AND uid IN (SELECT uid2 FROM friend WHERE uid1 = {0})".format(
        assoc.identifier)
    fb_friends = json.load(do_fql_query(fql_query, assoc.token))
    if 'error_code' not in fb_friends:
        return fb_friends
    return []
Example #22
0
def facebook_callback(request,
                      error_template_name="la_facebook/fb_error.html"):
    """
        1. define RequestContext
        2. access OAuth
        3. check session
        4. autheticate token
        5. raise exception if missing token
        6. return access callback
        7. raise exception if mismatch token
        8. render error 
    """

    ctx = RequestContext(request)
    access = OAuthAccess()
    # TODO: Check to make sure the session cookie is setting correctly
    unauth_token = request.session.get("unauth_token", None)
    try:
        auth_token = access.check_token(unauth_token, request.GET)
    except MissingToken:
        ctx.update({"error": "token_missing"})
        logger.error('la_facebook.views.facebook_callback: missing token')
    else:
        if auth_token:
            logger.debug('la_facebook.views.facebook_callback: token success '\
                    ', sending to callback')
            return access.callback(request, access, auth_token)
        else:
            # @@@ not nice for OAuth 2
            ctx.update({"error": "token_mismatch"})
            logger.error('la_facebook.views.facebook_callback: token mismatch'\
                    ', error getting token, or user denied FB login')

    # we either have a missing token or a token mismatch
    # Facebook provides some error details in the callback URL
    fb_errors = []
    for fb_error_detail in ['error', 'error_description', 'error_reason']:
        if fb_error_detail in request.GET:
            ctx['fb_' + fb_error_detail] = request.GET[fb_error_detail]
            fb_errors.append(request.GET[fb_error_detail])

    logger.warning('la_facebook.views.facebook_callback: %s' %
                   ', '.join(fb_errors))

    # Can't change to 401 error because that prompts basic browser auth
    return render_to_response(error_template_name, ctx)
Example #23
0
def facebook_callback(request, error_template_name="la_facebook/fb_error.html", fb_callback_path=None):
    """
        1. define RequestContext
        2. access OAuth
        3. check session
        4. autheticate token
        5. raise exception if missing token
        6. return access callback
        7. raise exception if mismatch token
        8. render error 
    """
    
    ctx = RequestContext(request)
    access = OAuthAccess(fb_callback_path=fb_callback_path)
    # TODO: Check to make sure the session cookie is setting correctly
    unauth_token = request.session.get("unauth_token", None)
    try:
        protocol = "https" if request.is_secure() else "http"
        auth_token = access.check_token(unauth_token, request.GET, protocol=protocol)
    except MissingToken:
        ctx.update({"error": "token_missing"})
        logger.error('la_facebook.views.facebook_callback: missing token')
    else:
        if auth_token:
            logger.debug('la_facebook.views.facebook_callback: token success '\
                    ', sending to callback')
            return access.callback(request, access, auth_token)
        else:
            # @@@ not nice for OAuth 2
            ctx.update({"error": "token_mismatch"})
            logger.error('la_facebook.views.facebook_callback: token mismatch'\
                    ', error getting token, or user denied FB login')

    # we either have a missing token or a token mismatch
    # Facebook provides some error details in the callback URL
    fb_errors = []
    for fb_error_detail in ['error', 'error_description', 'error_reason']:
        if fb_error_detail in request.GET:
            ctx['fb_' + fb_error_detail] = request.GET[fb_error_detail]
            fb_errors.append(request.GET[fb_error_detail])

    logger.warning('la_facebook.views.facebook_callback: %s'
            % ', '.join(fb_errors))

    # Can't change to 401 error because that prompts basic browser auth
    return render_to_response(error_template_name, ctx)
Example #24
0
def facebook_login(request, redirect_field_name="next",
                        redirect_to_session_key="redirect_to",
                        display="page"):
    """
        1. access OAuth
        2. set token to none
        3. store and redirect to authorization url
        4. redirect to OAuth authorization url
    """
    
    access = OAuthAccess()
    token = None
    if hasattr(request, "session"):
        logger.debug("la_facebook.views.facebook_login: request has session")
        # this session variable is used by the callback
        request.session[redirect_to_session_key] = request.GET.get(redirect_field_name)
    return HttpResponseRedirect(access.authorization_url(token, display=display))
Example #25
0
def facebook_login(request, redirect_field_name="next",
                        redirect_to_session_key="redirect_to",
                        display="page",
                        fb_callback_path=None):
    """
        1. access OAuth
        2. set token to none
        3. store and redirect to authorization url
        4. redirect to OAuth authorization url
    """
    
    access = OAuthAccess(fb_callback_path=fb_callback_path)
    token = None
    if hasattr(request, "session"):
        logger.debug("la_facebook.views.facebook_login: request has session")
        # this session variable is used by the callback
        request.session[redirect_to_session_key] = request.GET.get(redirect_field_name)
    protocol = "https" if request.is_secure() else "http"
    return HttpResponseRedirect(access.authorization_url(token, display=display, protocol=protocol))
    def create_user(self, request, access, token, user_data):
        identifier = self.identifier_from_data(user_data)
        User = get_user_model()
        USERNAME_FIELD = User.USERNAME_FIELD
        username = str(identifier)
        if User.objects.filter(**{USERNAME_FIELD: username}).count():
            logger.warning("DefaultFacebookCallback.create_user: A user for was already found, when asked to create a user for %s" % username)
            user = User.objects.get(**{USERNAME_FIELD: username})
        else:
            user = User(**{USERNAME_FIELD: str(identifier)})
            user.set_unusable_password()
            logger.debug(user_data)
            if 'email' in user_data:
                user.email = user_data["email"]
            user.save()
            logger.debug("DefaultFacebookCallback.create_user: new django user created for %s" % username)

        self.create_profile(request, access, token, user)
        self.handle_unauthenticated_user(request, user, access, token, user_data)
        return user
    def check_token(self, unauth_token, parameters):
        """
            check token
            check to see if unauthorized token
            if authorized token get code parameters
            return OAuth token
        """
        if unauth_token:
            logger.debug("OAuthAccess.check_token: have unauth_token %s"
                    % unauth_token)
            logger.debug("OAuthAccess.check_token: parameters: %s"
                    % parameters)
            token = oauth.Token.from_string(unauth_token)
            if token.key == parameters.get("oauth_token", "no_token"):
                verifier = parameters.get("oauth_verifier")
                return self.authorized_token(token, verifier)
            else:
                return None
        else:
            code = parameters.get("code")
            if code:
                params = dict(
                    client_id = self.key,
                    redirect_uri = self.callback_url,
                )
                params["client_secret"] = self.secret
                params["code"] = code
                logger.debug("OAuthAccess.check_token: token access params: "\
                        "%s, sent to %s" % (params, self.access_token_url))
                raw_data = urllib.urlopen(
                    "%s?%s" % (
                        self.access_token_url, urllib.urlencode(params)
                    )
                ).read()
                response = cgi.parse_qs(raw_data)
                logger.debug("OAuthAccess.check_token: response from code"\
                        "request: %s" % response)
                if 'expires' in response:
                    expires = int(response["expires"][-1])
                else:
                    expires = None

                return OAuth20Token(
                    response["access_token"][-1],
                    expires
                )
            else:
                # @@@ this error case is not nice
                logger.warning("OAuth20Token.check_token: no unauthorized" \
                        "token or code provided")
                return None
Example #28
0
    def redirect_url(
        self,
        request,
        fallback_url=settings.LOGIN_REDIRECT_URL,
        redirect_field_name="next",
        session_key_value="redirect_to",
    ):
        """
        Returns the URL to be used in login procedures by looking at different
        values in the following order:

        - a REQUEST value, GET or POST, named "next" by default.
        - LOGIN_REDIRECT_URL - the URL in the setting
        - LOGIN_REDIRECT_URLNAME - the name of a URLconf entry in the settings
        """

        redirect_to = request.REQUEST.get(redirect_field_name)
        if not redirect_to:
            logger.debug("redirect not in get params")
            # try the session if available
            if hasattr(request, "session"):
                redirect_to = request.session.get(session_key_value)
                # Heavier security check -- don't allow redirection to a different host.
                if redirect_to:
                    netloc = urlparse.urlparse(redirect_to)[1]
                    if netloc and netloc != request.host:
                        logger.warning("redirect_to host does not match orgin")
                        redirect_to = fallback_url
                else:
                    # There ought to have been a value in the session. This
                    # is probably a developer error, so log a warning.
                    logger.warning(
                        "Session found, but no redirect_to. Check "
                        "that you have set up the facebook_login "
                        "view with a 'next' querystring "
                        "parameter. Using fallback."
                    )
        if not redirect_to:
            logger.debug("no redirect found, using fallback")
            redirect_to = fallback_url
        return redirect_to
Example #29
0
    def check_token(self, unauth_token, parameters):
        """
            check token
            check to see if unauthorized token
            if authorized token get code parameters
            return OAuth token
        """
        if unauth_token:
            logger.debug("OAuthAccess.check_token: have unauth_token %s"
                    % unauth_token)
            logger.debug("OAuthAccess.check_token: parameters: %s"
                    % parameters)
            token = oauth.Token.from_string(unauth_token)
            if token.key == parameters.get("oauth_token", "no_token"):
                verifier = parameters.get("oauth_verifier")
                return self.authorized_token(token, verifier)
            else:
                return None
        else:
            code = parameters.get("code")
            if code:
                params = dict(
                    client_id = self.key,
                    redirect_uri = self.callback_url,
                )
                params["client_secret"] = self.secret
                params["code"] = code
                logger.debug("OAuthAccess.check_token: token access params: "\
                        "%s, sent to %s" % (params, self.access_token_url))
                raw_data = urllib.urlopen(
                    "%s?%s" % (
                        self.access_token_url, urllib.urlencode(params)
                    )
                ).read()
                response = cgi.parse_qs(raw_data)
                logger.debug("OAuthAccess.check_token: response from code"\
                        "request: %s" % response)
                if 'expires' in response:
                    expires = int(response["expires"][-1])
                else:
                    expires = None

                return OAuth20Token(
                    response["access_token"][-1],
                    expires
                )
            else:
                # @@@ this error case is not nice
                logger.warning("OAuth20Token.check_token: no unauthorized" \
                        "token or code provided")
                return None
Example #30
0
 def persist(self, user, token, user_data):
     """
         set expiration
         set defaults
         set identifier if not none
         if nothing was created save current associated defaults
     """
     expires = hasattr(token, "expires") and token.expires or None
     defaults = {
         "token": str(token),
         "expires": expires,
     }
     defaults["identifier"] = user_data['id']
     assoc, created = UserAssociation.objects.get_or_create(
         user = user,
         defaults = defaults,
     )
     if 'email' in user_data:
         # update user email
         if user.email != user_data['email']:
             user.email = user_data['email']
             user.save()
             logger.debug("Updated email for %s to %s" % (user,user_data['email']))
     if not created:
         assoc.token = str(token)
         assoc.expires = expires
         assoc.save()
         logger.debug("DefaultFacebookCallback.persist: UserAssociation " \
                 "object updated")
     else:
         logger.debug("DefaultFacebookCallback.persist: UserAssociation " \
                 "object created")
Example #31
0
 def persist(self, user, token, user_data):
     """
         set expiration
         set defaults
         set identifier if not none
         if nothing was created save current associated defaults
     """
     expires = hasattr(token, "expires") and token.expires or None
     defaults = {
         "token": str(token),
         "expires": expires,
     }
     defaults["identifier"] = user_data['id']
     assoc, created = UserAssociation.objects.get_or_create(
         user=user,
         defaults=defaults,
     )
     if 'email' in user_data:
         # update user email
         if user.email != user_data['email']:
             user.email = user_data['email']
             user.save()
             logger.debug("Updated email for %s to %s" %
                          (user, user_data['email']))
     if not created:
         assoc.token = str(token)
         assoc.expires = expires
         assoc.save()
         logger.debug("DefaultFacebookCallback.persist: UserAssociation " \
                 "object updated")
     else:
         logger.debug("DefaultFacebookCallback.persist: UserAssociation " \
                 "object created")
Example #32
0
    def create_user(self, request, access, token, user_data):
        identifier = self.identifier_from_data(user_data)
        username = str(identifier)
        if User.objects.filter(username=username).count():
            logger.warning("DefaultFacebookCallback.create_user: A user for" \
                    "was already found, when asked to create a user for %s"
                    % username)
            user = User.objects.get(username=username)
        else:
            user = User(username=str(identifier))
            user.set_unusable_password()
            logger.debug(user_data)
            if 'email' in user_data:
                user.email = user_data["email"]
            user.save()
            logger.debug("DefaultFacebookCallback.create_user: new django" \
                    "user created for %s" % username)

        self.create_profile(request, access, token, user)
        self.handle_unauthenticated_user(request, user, access, token,
                                         user_data)
        return user
Example #33
0
def get_friends_on_site(user):
    """ Find FB friends that are also using the site. """
    try:
        get_friends_internally = FACEBOOK_SETTINGS['STORE_FRIENDS']
    except KeyError:
        get_friends_internally = False

    if get_friends_internally:
        logger.debug('Getting friends internally for {0}'.format(user))
        friend_ids_on_site = Friend.objects.filter(uid1=user).values_list('uid2', flat=True)
        friend_user_associations = UserAssociation.objects.filter(user__pk__in=friend_ids_on_site).all()
        return friend_user_associations
    else:
        logger.debug('Getting friends from Facebook for {0}'.format(user))
        # going to FB for friendships.
        fb_friends = get_friends_on_facebook(user)
        if fb_friends:
            # even though the FQL query says that we should only have user id's that
            # are associated with our app, we're still going to filter against our
            # data in case there is some breakage (FB has them but we don't) 
            site_friends = UserAssociation.objects.filter(identifier__in=[i['uid'] for i in fb_friends])
            return site_friends
    return []
Example #34
0
 def login_user(self, request, user):
     user.backend = "django.contrib.auth.backends.ModelBackend"
     logger.debug("DefaultFacebookCallback.login_user: logging in user %s" \
             " with ModelBackend" % str(user).strip())
     login(request, user)
Example #35
0
    def post(self, request, format=None):
        
        #return 200 if user is already authenticated
        if request.user is not None :
            logger.debug("mobileauth invoked with user %s on session" % request.user);
            if request.user.is_authenticated():
                logger.debug("mobileauth invoked with authenticated user on session");
                return Response(None,status=204);

        #validate the access token by hitting graph.facebook.com
        fbAuthToken = request.DATA['access_token'];
        if fbAuthToken is None:
            return Response("access_token is missing", status=400);
        urlStream = urllib.urlopen("https://graph.facebook.com/me?access_token=%s" % fbAuthToken);
        raw_data = urlStream.read();
        fbResponseCode = urlStream.getcode();
        if fbResponseCode <> 200:
            logger.debug("failed to verify access token. response code: %s. message: %s" % (fbResponseCode, raw_data));
            return Response("failed to verify access token", status=500);
        fbResponse = json.loads(raw_data);
        fbUserId = fbResponse['id'];
        
        #let an instance of the LaFacebook default callback handle Django auth
        lafbCallback = DefaultFacebookCallback()
        existing_user = lafbCallback.lookup_user(None, None, fbResponse);
        logger.debug("existing user? %s" % existing_user);
        if existing_user is None:
            #create user record
            access = OAuthAccess()
            existing_user = lafbCallback.create_user(request._request, access, OAuth20Token(fbAuthToken), fbResponse);
        else:
            username = existing_user.username;
            logger.debug("query for user %s" % username);
            userObj = User.objects.get(username=username);
            lafbCallback.login_user(request._request, userObj);
            
        #return success & the user id if everything worked
        response = {};
        response['id'] = fbResponse['id'];
        logger.debug("existing_user %s", existing_user);
        authUserPk = existing_user.id;
        response['token'] = Token.objects.get(user=existing_user).key;
        logger.debug("csrf dict: %s" % csrf.get_token(request));
        if existing_user.is_authenticated():
            return Response(response, status=200);
        else:
            return Response("Authentication failed for %s" % fbUserId, status=500);
Example #36
0
    def do_friends_update(self, user):
        logger.debug('Starting friends update.')
        friends_on_facebook = []
        for friend in get_friends_on_facebook(user):
            friends_on_facebook.append(str(friend['uid']))

        # friends_on_facebook contains the FB id's of users that
        # facebook says has auth'd the app

        friend_ids_on_site = Friend.objects.filter(uid1=user).values_list(
            'uid2', flat=True)
        friend_user_associations = UserAssociation.objects.filter(
            user__pk__in=friend_ids_on_site)

        # friend_user_associations contains the UserAssociation objects for all
        # Friend relationships that are stored in the app.

        friends_to_delete = []
        for ua in friend_user_associations:
            id = ua.identifier
            logger.debug('Checking FB id: {0}'.format(id))
            try:
                # check to see if we already have a user association for the facebook friend
                # if we do, it needs to be removed from the add list
                friends_on_facebook.index(id)
            except ValueError:
                # FB does not have a friendship for the given id stored in the app.
                # The friendship needs to be removed from the app.
                logger.debug('Adding {0} to delete list.'.format(id))
                friends_to_delete.append(id)
            else:
                # both the app and FB have this friendship. The id needs to be
                # removed from friends_on_facebook as anything left in it will
                # be added as a new friendship in the app.
                try:
                    logger.debug('Removing {0} from add list.'.format(id))
                    friends_on_facebook.remove(id)
                except ValueError:
                    logger.debug(
                        'Error removing {0} from friends list.'.format(id))

        logger.debug('Adding friends with facebook ids: {0}'.format(
            friends_on_facebook))

        #get user associations for facebook friends to add.
        users = list(
            UserAssociation.objects.filter(
                identifier__in=friends_on_facebook).select_related('user'))
        for u in users:
            Friend.objects.create(uid1=user, uid2=u.user)
            Friend.objects.create(uid1=u.user, uid2=user)

        #get user associations for facebook friends to delete
        logger.debug('Deleting friends with facebook ids: {0}'.format(
            friends_to_delete))
        users = list(
            UserAssociation.objects.filter(
                identifier__in=friends_to_delete).select_related('user'))
        for u in users:
            Friend.objects.filter(uid1=user, uid2=u.user).delete()
            Friend.objects.filter(uid1=u.user, uid2=user).delete()
Example #37
0
 def login_user(self, request, user):
     user.backend = "django.contrib.auth.backends.ModelBackend"
     logger.debug("DefaultFacebookCallback.login_user: logging in user %s" \
             " with ModelBackend" % str(user).strip())
     login(request, user)
Example #38
0
    def do_friends_update(self, user):
        logger.debug('Starting friends update.')
        friends_on_facebook = []
        for friend in get_friends_on_facebook(user):
            friends_on_facebook.append(str(friend['uid']))

        # friends_on_facebook contains the FB id's of users that
        # facebook says has auth'd the app

        friend_ids_on_site = Friend.objects.filter(uid1=user).values_list('uid2', flat=True)
        friend_user_associations = UserAssociation.objects.filter(user__pk__in=friend_ids_on_site)

        # friend_user_associations contains the UserAssociation objects for all
        # Friend relationships that are stored in the app.

        friends_to_delete = []
        for ua in friend_user_associations:
            id = ua.identifier
            logger.debug('Checking FB id: {0}'.format(id))
            try:
                # check to see if we already have a user association for the facebook friend
                # if we do, it needs to be removed from the add list
                friends_on_facebook.index(id)
            except ValueError:
                # FB does not have a friendship for the given id stored in the app.
                # The friendship needs to be removed from the app.
                logger.debug('Adding {0} to delete list.'.format(id))
                friends_to_delete.append(id)
            else:
                # both the app and FB have this friendship. The id needs to be
                # removed from friends_on_facebook as anything left in it will
                # be added as a new friendship in the app.
                try:
                    logger.debug('Removing {0} from add list.'.format(id))
                    friends_on_facebook.remove(id)
                except ValueError:
                    logger.debug('Error removing {0} from friends list.'.format(id))

        logger.debug('Adding friends with facebook ids: {0}'.format(friends_on_facebook))

        #get user associations for facebook friends to add.
        users = list(UserAssociation.objects.filter(identifier__in=friends_on_facebook).select_related('user'))
        for u in users:
            Friend.objects.create(uid1=user, uid2=u.user)
            Friend.objects.create(uid1=u.user, uid2=user)

        #get user associations for facebook friends to delete
        logger.debug('Deleting friends with facebook ids: {0}'.format(friends_to_delete))
        users = list(UserAssociation.objects.filter(identifier__in=friends_to_delete).select_related('user'))
        for u in users:
            Friend.objects.filter(uid1=user, uid2=u.user).delete()
            Friend.objects.filter(uid1=u.user, uid2=user).delete()