コード例 #1
0
    def post(self, request, *args, **kwargs):
        grant_type = request.POST.get('grant_type', 'password')
        username = request.POST.get('username')

        # pre-validate scopes requested
        client_id = request.POST.get('client_id', None)
        requested_scopes = [s for s in scope_to_list(request.POST.get('scope', '')) if s]
        if client_id:
            try:
                oauth_app = Application.objects.get(client_id=client_id)
            except Application.DoesNotExist:
                return HttpResponse(json.dumps({"error": "invalid client_id"}), status=HTTP_400_BAD_REQUEST)

            try:
                allowed_scopes = oauth_app.applicationinfo.scope_list
            except ApplicationInfo.DoesNotExist:
                allowed_scopes = ['r:profile']

            # handle rw:issuer:* scopes
            if 'rw:issuer:*' in allowed_scopes:
                issuer_scopes = filter(lambda x: x.startswith(r'rw:issuer:'), requested_scopes)
                allowed_scopes.extend(issuer_scopes)

            filtered_scopes = set(allowed_scopes) & set(requested_scopes)
            if len(filtered_scopes) < len(requested_scopes):
                return HttpResponse(json.dumps({"error": "invalid scope requested"}), status=HTTP_400_BAD_REQUEST)

        # let parent method do actual authentication
        response = super(TokenView, self).post(request, *args, **kwargs)

        if grant_type == "password" and response.status_code == 401:
            badgrlogger.event(badgrlog.FailedLoginAttempt(request, username, endpoint='/o/token'))

        return response
コード例 #2
0
ファイル: admin.py プロジェクト: saskeroms/badgr-server
    def login(self, request, extra_context=None):
        response = super(BadgrAdminSite, self).login(request, extra_context)
        if request.method == 'POST':
            # form submission
            if response.status_code != 302:
                # failed /staff login
                username = request.POST.get('username', None)
                badgrlogger.event(badgrlog.FailedLoginAttempt(request, username, endpoint='/staff/login'))

        return response
コード例 #3
0
ファイル: oauth2_api.py プロジェクト: jeborsel/badgr-server
    def post(self, request, *args, **kwargs):
        def _request_identity(request):
            username = request.POST.get('username', None)
            if username:
                return username
            return client_ip_from_request(self.request)

        def _backoff_cache_key(request):
            return "failed_token_backoff_{}".format(_request_identity(request))

        _backoff_period = getattr(settings, 'TOKEN_BACKOFF_PERIOD_SECONDS', 2)

        grant_type = request.POST.get('grant_type', 'password')

        if grant_type == 'password' and _backoff_period is not None:
            # check for existing backoff for password attempts
            backoff = cache.get(_backoff_cache_key(request))
            if backoff is not None:
                backoff_until = backoff.get('until', None)
                backoff_count = backoff.get('count', 1)
                if backoff_until > timezone.now():
                    backoff_count += 1
                    backoff_seconds = min(
                        86400, _backoff_period**
                        backoff_count)  # maximum backoff is 24 hours
                    backoff_until = timezone.now() + datetime.timedelta(
                        seconds=backoff_seconds)
                    cache.set(_backoff_cache_key(request),
                              dict(until=backoff_until, count=backoff_count),
                              timeout=None)
                    # return the same error as a failed login attempt
                    return HttpResponse(json.dumps({
                        "error_description": "Invalid credentials given.",
                        "error": "invalid_grant"
                    }),
                                        status=HTTP_401_UNAUTHORIZED)

        # pre-validate scopes requested
        client_id = request.POST.get('client_id', None)
        requested_scopes = [
            s for s in scope_to_list(request.POST.get('scope', '')) if s
        ]
        if client_id:
            try:
                oauth_app = Application.objects.get(client_id=client_id)
            except Application.DoesNotExist:
                return HttpResponse(json.dumps({"error": "invalid client_id"}),
                                    status=HTTP_400_BAD_REQUEST)

            try:
                allowed_scopes = oauth_app.applicationinfo.scope_list
            except ApplicationInfo.DoesNotExist:
                allowed_scopes = ['r:profile']

            # handle rw:issuer:* scopes
            if 'rw:issuer:*' in allowed_scopes:
                issuer_scopes = [
                    x for x in requested_scopes if x.startswith(r'rw:issuer:')
                ]
                allowed_scopes.extend(issuer_scopes)

            filtered_scopes = set(allowed_scopes) & set(requested_scopes)
            if len(filtered_scopes) < len(requested_scopes):
                return HttpResponse(json.dumps(
                    {"error": "invalid scope requested"}),
                                    status=HTTP_400_BAD_REQUEST)

        # let parent method do actual authentication
        response = super(TokenView, self).post(request, *args, **kwargs)

        if grant_type == "password" and response.status_code == 401:
            # failed password login attempt
            username = request.POST.get('username', None)
            badgrlogger.event(
                badgrlog.FailedLoginAttempt(request,
                                            username,
                                            endpoint='/o/token'))

            if _backoff_period is not None:
                # update backoff for failed logins
                backoff = cache.get(_backoff_cache_key(request))
                if backoff is None:
                    backoff = {'count': 0}
                backoff['count'] += 1
                backoff['until'] = timezone.now() + datetime.timedelta(
                    seconds=_backoff_period**backoff['count'])
                cache.set(_backoff_cache_key(request), backoff, timeout=None)
        elif response.status_code == 200:
            # successful login
            cache.set(_backoff_cache_key(request),
                      None)  # clear any existing backoff

        return response
コード例 #4
0
    def post(self, request, *args, **kwargs):
        if len(request.GET):
            return HttpResponse(json.dumps({
                "error":
                "Token grant parameters must be sent in post body, not query parameters"
            }),
                                status=HTTP_400_BAD_REQUEST)

        grant_type = request.POST.get('grant_type', 'password')
        username = request.POST.get('username')
        client_id = None

        try:
            auth_header = request.META['HTTP_AUTHORIZATION']
            credentials = auth_header.split(' ')
            if credentials[0] == 'Basic':
                client_id, client_secret = base64.b64decode(
                    credentials[1].encode('ascii')).decode('ascii').split(':')
        except (KeyError, IndexError, ValueError, TypeError):
            client_id = request.POST.get('client_id', None)
            client_secret = None

        # pre-validate scopes requested

        requested_scopes = [
            s for s in scope_to_list(request.POST.get('scope', '')) if s
        ]
        oauth_app = None
        if client_id:
            try:
                oauth_app = Application.objects.get(client_id=client_id)
                if client_secret and oauth_app.client_secret != client_secret:
                    return HttpResponse(json.dumps(
                        {"error": "invalid client_secret"}),
                                        status=HTTP_400_BAD_REQUEST)
            except Application.DoesNotExist:
                return HttpResponse(json.dumps({"error": "invalid client_id"}),
                                    status=HTTP_400_BAD_REQUEST)

            try:
                allowed_scopes = oauth_app.applicationinfo.scope_list
            except ApplicationInfo.DoesNotExist:
                allowed_scopes = ['r:profile']

            # handle rw:issuer:* scopes
            if 'rw:issuer:*' in allowed_scopes:
                issuer_scopes = [
                    x for x in requested_scopes if x.startswith(r'rw:issuer:')
                ]
                allowed_scopes.extend(issuer_scopes)

            filtered_scopes = set(allowed_scopes) & set(requested_scopes)
            if len(filtered_scopes) < len(requested_scopes):
                return HttpResponse(json.dumps(
                    {"error": "invalid scope requested"}),
                                    status=HTTP_400_BAD_REQUEST)

        # let parent method do actual authentication
        response = super(TokenView, self).post(request, *args, **kwargs)

        if oauth_app and not oauth_app.applicationinfo.issue_refresh_token:
            data = json.loads(response.content)
            try:
                del data['refresh_token']
            except KeyError:
                pass
            response.content = json.dumps(data)

        if grant_type == "password" and response.status_code == 401:
            badgrlogger.event(
                badgrlog.FailedLoginAttempt(request,
                                            username,
                                            endpoint='/o/token'))

        return response