This file is indexed.

/usr/share/pyshared/social_auth/backends/contrib/stackoverflow.py is in python-django-social-auth 0.7.23-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
"""
Stackoverflow OAuth support.

This contribution adds support for Stackoverflow OAuth service. The settings
STACKOVERFLOW_CLIENT_ID, STACKOVERFLOW_CLIENT_SECRET and
STACKOVERFLOW_CLIENT_SECRET must be defined with the values given by
Stackoverflow application registration process.

Extended permissions are supported by defining
STACKOVERFLOW_EXTENDED_PERMISSIONS setting, it must be a list of values
to request.

By default account id and token expiration time are stored in extra_data
field, check OAuthBackend class for details on how to extend it.
"""
from urllib import urlencode
from urllib2 import Request, HTTPError
from urlparse import parse_qsl
from gzip import GzipFile
from StringIO import StringIO

from django.utils import simplejson
from django.conf import settings

from social_auth.utils import dsa_urlopen
from social_auth.backends import BaseOAuth2, OAuthBackend
from social_auth.exceptions import AuthUnknownError, AuthCanceled


# Stackoverflow configuration
STACKOVERFLOW_AUTHORIZATION_URL = 'https://stackexchange.com/oauth'
STACKOVERFLOW_ACCESS_TOKEN_URL = 'https://stackexchange.com/oauth/access_token'
STACKOVERFLOW_USER_DATA_URL = 'https://api.stackexchange.com/2.1/me'

STACKOVERFLOW_SERVER = 'stackexchange.com'


class StackoverflowBackend(OAuthBackend):
    """Stackoverflow OAuth authentication backend"""
    name = 'stackoverflow'
    ID_KEY = 'user_id'
    # Default extra data to store
    EXTRA_DATA = [
        ('id', 'id'),
        ('expires', 'expires')
    ]

    def get_user_details(self, response):
        """Return user details from Stackoverflow account"""
        return {'username': response.get('link').split('/')[-1],
                'full_name': response.get('display_name')}


class StackoverflowAuth(BaseOAuth2):
    """Stackoverflow OAuth2 mechanism"""
    AUTHORIZATION_URL = STACKOVERFLOW_AUTHORIZATION_URL
    ACCESS_TOKEN_URL = STACKOVERFLOW_ACCESS_TOKEN_URL
    AUTH_BACKEND = StackoverflowBackend
    SETTINGS_KEY_NAME = 'STACKOVERFLOW_CLIENT_ID'
    SETTINGS_SECRET_NAME = 'STACKOVERFLOW_CLIENT_SECRET'
    SCOPE_SEPARATOR = ','
    # See: https://api.stackexchange.com/docs/authentication#scope
    SCOPE_VAR_NAME = 'STACKOVERFLOW_EXTENDED_PERMISSIONS'

    def auth_complete(self, *args, **kwargs):
        """Completes loging process, must return user instance"""
        self.process_error(self.data)
        params = self.auth_complete_params(self.validate_state())
        request = Request(self.ACCESS_TOKEN_URL, data=urlencode(params),
                          headers=self.auth_headers())

        try:
            response = dict(parse_qsl(dsa_urlopen(request).read()))
        except HTTPError, e:
            if e.code == 400:
                raise AuthCanceled(self)
            else:
                raise
        except (ValueError, KeyError):
            raise AuthUnknownError(self)

        self.process_error(response)
        return self.do_auth(response['access_token'], response=response,
                            *args, **kwargs)

    def user_data(self, access_token, *args, **kwargs):
        """Loads user data from service"""
        url = STACKOVERFLOW_USER_DATA_URL + '?' + urlencode({
            'site': 'stackoverflow',
            'access_token': access_token,
            'key': getattr(settings, 'STACKOVERFLOW_KEY')})

        opener = dsa_urlopen(url)
        if opener.headers.get('content-encoding') == 'gzip':
            ''' stackoverflow doesn't respect no gzip header '''
            gzip = GzipFile(fileobj=StringIO(opener.read()), mode='r')
            response = gzip.read()
        else:
            response = opener.read()

        try:
            data = simplejson.loads(response)
            return data.get('items')[0]
        except (ValueError, TypeError):
            return None

# Backend definition
BACKENDS = {
    'stackoverflow': StackoverflowAuth,
}