コード例 #1
0
ファイル: provider.py プロジェクト: commonlims/commonlims
    def refresh_identity(self, identity, *args, **kwargs):
        refresh_token = identity.data.get('refresh_token')
        refresh_token_url = kwargs.get('refresh_token_url')

        if not refresh_token:
            raise IdentityNotValid('Missing refresh token')

        if not refresh_token_url:
            raise IdentityNotValid('Missing refresh token url')

        data = self.get_refresh_token_params(refresh_token, *args, **kwargs)

        req = safe_urlopen(
            url=refresh_token_url,
            headers={},
            data=data,
        )

        try:
            body = safe_urlread(req)
            payload = json.loads(body)
        except Exception:
            payload = {}

        self.handle_refresh_error(req, payload)

        identity.data.update(get_oauth_data(payload))
        return identity.update(data=identity.data)
コード例 #2
0
    def refresh_identity(self, identity, *args, **kwargs):
        refresh_token = identity.data.get("refresh_token")
        refresh_token_url = kwargs.get("refresh_token_url")

        if not refresh_token:
            raise IdentityNotValid("Missing refresh token")

        if not refresh_token_url:
            raise IdentityNotValid("Missing refresh token url")

        data = self.get_refresh_token_params(refresh_token, *args, **kwargs)

        req = safe_urlopen(url=refresh_token_url, headers={}, data=data)

        try:
            body = safe_urlread(req)
            payload = json.loads(body)
        except Exception as e:
            self.logger(
                "gitlab.refresh-identity-failure",
                extra={
                    "identity_id": identity.id,
                    "error_status": e.code,
                    "error_message": str(e),
                },
            )
            payload = {}

        self.handle_refresh_error(req, payload)

        identity.data.update(get_oauth_data(payload))
        return identity.update(data=identity.data)
コード例 #3
0
    def refresh_identity(self, identity, *args, **kwargs):
        refresh_token = identity.data.get('refresh_token')
        refresh_token_url = kwargs.get('refresh_token_url')

        if not refresh_token:
            raise IdentityNotValid('Missing refresh token')

        if not refresh_token_url:
            raise IdentityNotValid('Missing refresh token url')

        data = self.get_refresh_token_params(refresh_token, *args, **kwargs)

        req = safe_urlopen(
            url=refresh_token_url,
            headers={},
            data=data,
        )

        try:
            body = safe_urlread(req)
            payload = json.loads(body)
        except Exception as e:
            self.logger('gitlab.refresh-identity-failure',
                        extra={
                            'identity_id': identity.id,
                            'error_status': e.code,
                            'error_message': e.message,
                        })
            payload = {}

        self.handle_refresh_error(req, payload)

        identity.data.update(get_oauth_data(payload))
        return identity.update(data=identity.data)
コード例 #4
0
ファイル: oauth2.py プロジェクト: pasala91/test
    def refresh_identity(self, auth_identity):
        refresh_token = auth_identity.data.get("refresh_token")

        if not refresh_token:
            raise IdentityNotValid("Missing refresh token")

        data = self.get_refresh_token_params(refresh_token=refresh_token)
        req = safe_urlopen(self.get_refresh_token_url(), data=data)

        try:
            body = safe_urlread(req)
            payload = json.loads(body)
        except Exception:
            payload = {}

        error = payload.get("error", "unknown_error")
        error_description = payload.get("error_description", "no description available")

        formatted_error = f"HTTP {req.status_code} ({error}): {error_description}"

        if req.status_code == 401:
            raise IdentityNotValid(formatted_error)

        if req.status_code == 400:
            # this may not be common, but at the very least Google will return
            # an invalid grant when a user is suspended
            if error == "invalid_grant":
                raise IdentityNotValid(formatted_error)

        if req.status_code != 200:
            raise Exception(formatted_error)

        auth_identity.data.update(self.get_oauth_data(payload))
        auth_identity.update(data=auth_identity.data)
コード例 #5
0
ファイル: provider.py プロジェクト: zttzxh/sentry
    def build_identity(self, state):
        data = state["data"]

        try:
            id_token = data["id_token"]
        except KeyError:
            raise IdentityNotValid(u"Missing id_token in OAuth response: %s" % data)

        try:
            _, payload, _ = map(urlsafe_b64decode, id_token.split(".", 2))
        except Exception as exc:
            raise IdentityNotValid(u"Unable to decode id_token: %s" % exc)

        try:
            user_data = json.loads(payload)
        except ValueError as exc:
            raise IdentityNotValid(u"Unable to decode id_token payload: %s" % exc)

        # XXX(epurkhiser): This is carryover from the AuthProvider version of
        # google identity. Because we will have code that handles interop
        # between newstyle generic Identity, and oldstyle AuthProviders, we
        # have to keep the MigratingIdentityId here.
        user_id = MigratingIdentityId(id=user_data["sub"], legacy_id=user_data["email"])

        return {
            "type": "google",
            "id": user_id,
            "email": user_data["email"],
            "email_verified": user_data["email_verified"],
            "name": user_data["email"],
            "domain": user_data.get("hd", DEFAULT_GOOGLE_DOMAIN),
            "scopes": sorted(self.oauth_scopes),
            "data": self.get_oauth_data(data),
        }
コード例 #6
0
ファイル: oauth2.py プロジェクト: zhouhuiquan/sentry
    def handle_refresh_error(self, req, payload):
        error_name = 'unknown_error'
        error_description = 'no description available'
        for name_key in ['error', 'Error']:
            if name_key in payload:
                error_name = payload.get(name_key)
                break

        for desc_key in ['error_description', 'ErrorDescription']:
            if desc_key in payload:
                error_description = payload.get(desc_key)
                break

        formatted_error = u'HTTP {} ({}): {}'.format(req.status_code, error_name, error_description)

        if req.status_code == 401:
            raise IdentityNotValid(formatted_error)

        if req.status_code == 400:
            # this may not be common, but at the very least Google will return
            # an invalid grant when a user is suspended
            if error_name == 'invalid_grant':
                raise IdentityNotValid(formatted_error)

        if req.status_code != 200:
            raise ApiError(formatted_error)
コード例 #7
0
ファイル: oauth2.py プロジェクト: zlcoming/sentry
    def handle_refresh_error(self, req, payload):
        error_name = "unknown_error"
        error_description = "no description available"
        for name_key in ["error", "Error"]:
            if name_key in payload:
                error_name = payload.get(name_key)
                break

        for desc_key in ["error_description", "ErrorDescription"]:
            if desc_key in payload:
                error_description = payload.get(desc_key)
                break

        formatted_error = u"HTTP {} ({}): {}".format(req.status_code,
                                                     error_name,
                                                     error_description)

        if req.status_code == 401:
            self.logger.info(
                "identity.oauth.refresh.identity-not-valid-error",
                extra={
                    "error_name": error_name,
                    "error_status_code": req.status_code,
                    "error_description": error_description,
                    "provider_key": self.key,
                },
            )
            raise IdentityNotValid(formatted_error)

        if req.status_code == 400:
            # this may not be common, but at the very least Google will return
            # an invalid grant when a user is suspended
            if error_name == "invalid_grant":
                self.logger.info(
                    "identity.oauth.refresh.identity-not-valid-error",
                    extra={
                        "error_name": error_name,
                        "error_status_code": req.status_code,
                        "error_description": error_description,
                        "provider_key": self.key,
                    },
                )
                raise IdentityNotValid(formatted_error)

        if req.status_code != 200:
            self.logger.info(
                "identity.oauth.refresh.api-error",
                extra={
                    "error_name": error_name,
                    "error_status_code": req.status_code,
                    "error_description": error_description,
                    "provider_key": self.key,
                },
            )
            raise ApiError(formatted_error)
コード例 #8
0
ファイル: oauth2.py プロジェクト: luckylk/sentry
    def handle_refresh_error(self, req, payload):
        error_name = 'unknown_error'
        error_description = 'no description available'
        for name_key in ['error', 'Error']:
            if name_key in payload:
                error_name = payload.get(name_key)
                break

        for desc_key in ['error_description', 'ErrorDescription']:
            if desc_key in payload:
                error_description = payload.get(desc_key)
                break

        formatted_error = u'HTTP {} ({}): {}'.format(req.status_code, error_name, error_description)

        if req.status_code == 401:
            self.logger.info(
                'identity.oauth.refresh.identity-not-valid-error',
                extra={
                    'error_name': error_name,
                    'error_status_code': req.status_code,
                    'error_description': error_description,
                    'provider_key': self.key,
                }
            )
            raise IdentityNotValid(formatted_error)

        if req.status_code == 400:
            # this may not be common, but at the very least Google will return
            # an invalid grant when a user is suspended
            if error_name == 'invalid_grant':
                self.logger.info(
                    'identity.oauth.refresh.identity-not-valid-error',
                    extra={
                        'error_name': error_name,
                        'error_status_code': req.status_code,
                        'error_description': error_description,
                        'provider_key': self.key,
                    }
                )
                raise IdentityNotValid(formatted_error)

        if req.status_code != 200:
            self.logger.info(
                'identity.oauth.refresh.api-error',
                extra={
                    'error_name': error_name,
                    'error_status_code': req.status_code,
                    'error_description': error_description,
                    'provider_key': self.key,
                }
            )
            raise ApiError(formatted_error)
コード例 #9
0
 def refresh_identity(self, auth_identity):
     with GitHubClient(auth_identity.data["access_token"]) as client:
         try:
             if not client.is_org_member(self.org["id"]):
                 raise IdentityNotValid
         except GitHubApiError as e:
             raise IdentityNotValid(e)
コード例 #10
0
    def build_identity(self, state):
        raw_attributes = state["auth_attributes"]
        attributes = {}

        # map configured provider attributes
        for key, provider_key in iteritems(self.config["attribute_mapping"]):
            attributes[key] = raw_attributes.get(provider_key, [""])[0]

        # Email and identifier MUST be correctly mapped
        if not attributes[Attributes.IDENTIFIER] or not attributes[Attributes.USER_EMAIL]:
            raise IdentityNotValid(
                _(
                    "Failed to map SAML attributes. Assertion returned the following attribute keys: %(keys)s"
                )
                % {"keys": raw_attributes.keys()}
            )

        name = (attributes[k] for k in (Attributes.FIRST_NAME, Attributes.LAST_NAME))
        name = " ".join(filter(None, name))

        return {
            "id": attributes[Attributes.IDENTIFIER],
            "email": attributes[Attributes.USER_EMAIL],
            "name": name,
        }
コード例 #11
0
    def build_identity(self, state):
        raw_attributes = state["auth_attributes"]
        attributes = {}

        # map configured provider attributes
        for key, provider_key in self.config["attribute_mapping"].items():
            attribute_list = raw_attributes.get(provider_key, [""])
            attributes[key] = attribute_list[0] if len(attribute_list) > 0 else ""

        # Email and identifier MUST be correctly mapped
        if not attributes[Attributes.IDENTIFIER] or not attributes[Attributes.USER_EMAIL]:
            error_msg_keys = ", ".join(repr(key) for key in sorted(raw_attributes.keys()))
            raise IdentityNotValid(
                _(
                    f"Failed to map SAML attributes. Assertion returned the following attribute keys: {error_msg_keys}"
                )
            )

        name = (attributes[k] for k in (Attributes.FIRST_NAME, Attributes.LAST_NAME))
        name = " ".join(_f for _f in name if _f)

        return {
            "id": attributes[Attributes.IDENTIFIER],
            "email": attributes[Attributes.USER_EMAIL],
            "name": name,
        }
コード例 #12
0
    def test_simple(self, mock_check_auth_identity):
        organization = self.create_organization(name='Test')
        user = self.create_user(email='*****@*****.**')
        auth_provider = AuthProvider.objects.create(
            organization=organization,
            provider='dummy',
        )
        om = OrganizationMember.objects.create(
            user=user,
            organization=organization,
            flags=OrganizationMember.flags['sso:linked'],
        )

        ai = AuthIdentity.objects.create(
            auth_provider=auth_provider,
            user=user,
            last_verified=timezone.now() - timedelta(days=1),
        )

        with patch.object(DummyProvider, 'refresh_identity') as mock_refresh_identity:
            mock_refresh_identity.side_effect = IdentityNotValid()
            with self.auth_provider('dummy', DummyProvider):
                check_auth_identity(auth_identity_id=ai.id)
            mock_refresh_identity.assert_called_once_with(ai)

        # because of an error, it should become inactive
        om = OrganizationMember.objects.get(id=om.id)
        assert not om.flags['sso:linked']
        assert om.flags['sso:invalid']

        updated_ai = AuthIdentity.objects.get(id=ai.id)
        assert updated_ai.last_synced != ai.last_synced
        assert updated_ai.last_verified != ai.last_verified
コード例 #13
0
    def test_basic_flow_error(self, build_identity, logger):
        build_identity.side_effect = IdentityNotValid()

        user = self.create_user("*****@*****.**")
        organization = self.create_organization(name="foo", owner=user)

        self.login_as(user)
        self.assert_basic_flow(user, organization, expect_error=True)
コード例 #14
0
    def refresh_identity(self, auth_identity):
        client = GenericClient(self.client_id, self.client_secret)
        access_token = auth_identity.data['access_token']

        try:
            if not client.get_user(access_token):
                raise IdentityNotValid
        except GenericApiError as e:
            raise IdentityNotValid(e)
コード例 #15
0
    def refresh_identity(self, auth_identity):
        client = GitLabClient(self.client_id, self.client_secret)
        access_token = auth_identity.data['access_token']

        try:
            if not client.is_org_member(access_token, self.org['id']):
                raise IdentityNotValid
        except GitLabApiError as e:
            raise IdentityNotValid(e)
コード例 #16
0
    def refresh_identity(self, auth_identity):
        client = ThaliaClient()
        try:
            user_data = client.get_user(auth_identity.data['auth_token'])

            auth_identity.user.update(name=u'{} {}'.format(
                user_data['first_name'], user_data['last_name']),
                                      email=user_data['email'])
        except ThaliaApiError as e:
            raise IdentityNotValid(e.message)
コード例 #17
0
    def dispatch(self, request, organization_slug):
        provider = get_provider(organization_slug)
        organization = Organization.objects.get(slug=organization_slug)
        saml_config = provider.build_saml_config(organization_slug)

        auth = provider.build_auth(request, saml_config)
        auth.process_response()
        errors = auth.get_errors()
        if errors:
            error_reason = auth.get_last_error_reason()
            raise IdentityNotValid(error_reason)

        attributes = auth.get_attributes()
        nameid = auth.get_nameid()

        email = self.retrieve_email(attributes, nameid, provider.config)

        # Filter users based on the emails provided in the commits
        user_emails = list(
            UserEmail.objects.filter(email__iexact=email,
                                     is_verified=True).order_by('id'))

        if user_emails:
            users = list(
                User.objects.filter(
                    id__in=set((ue.user_id for ue in user_emails)),
                    is_active=True,
                    sentry_orgmember_set__organization_id=organization.id)
                [0:2])
            if users:
                if len(users) == 1:
                    user = users[0]
                    user.backend = settings.AUTHENTICATION_BACKENDS[0]
                    if login(request,
                             user,
                             after_2fa=request.build_absolute_uri(),
                             organization_id=organization.id):
                        request.session['saml'] = {
                            'nameid': nameid,
                            'nameid_format': auth.get_nameid_format(),
                            'session_index': auth.get_session_index()
                        }
                    return HttpResponseRedirect(get_login_redirect(request))
                else:
                    return HttpResponseServerError(
                        "Found several accounts related with %s on this organization"
                        % email)
            else:
                return HttpResponseServerError(
                    "The user %s is not related with this organization" %
                    email)
        else:
            return HttpResponseServerError(
                "An user with a verified mail: %s does not exist" % email)
コード例 #18
0
    def refresh_identity(self, identity, *args, **kwargs):
        refresh_token = identity.data.get('refresh_token')

        if not refresh_token:
            raise IdentityNotValid('Missing refresh token')

        data = self.get_refresh_token_params(refresh_token, *args, **kwargs)

        req = safe_urlopen(
            url=self.get_refresh_token_url(),
            headers=self.get_refresh_token_headers(),
            data=data,
        )

        try:
            body = safe_urlread(req)
            payload = json.loads(body)
        except Exception:
            payload = {}

        error = payload.get('error', 'unknown_error')
        error_description = payload.get('error_description',
                                        'no description available')

        formatted_error = 'HTTP {} ({}): {}'.format(req.status_code, error,
                                                    error_description)

        if req.status_code == 401:
            raise IdentityNotValid(formatted_error)

        if req.status_code == 400:
            # this may not be common, but at the very least Google will return
            # an invalid grant when a user is suspended
            if error == 'invalid_grant':
                raise IdentityNotValid(formatted_error)

        if req.status_code != 200:
            raise Exception(formatted_error)

        identity.data.update(self.get_oauth_data(payload))
        return identity.update(data=identity.data)
コード例 #19
0
ファイル: provider.py プロジェクト: wangjianweiwei/sentry
    def refresh_identity(self, identity, *args, **kwargs):
        refresh_token = identity.data.get("refresh_token")
        refresh_token_url = kwargs.get("refresh_token_url")

        if not refresh_token:
            raise IdentityNotValid("Missing refresh token")

        if not refresh_token_url:
            raise IdentityNotValid("Missing refresh token url")

        kwargs["identity"] = identity
        data = self.get_refresh_token_params(refresh_token, *args, **kwargs)

        req = safe_urlopen(url=refresh_token_url, headers={}, data=data)

        try:
            body = safe_urlread(req)
            payload = json.loads(body)
        except Exception as e:
            # JSONDecodeError's will happen when we get a 301
            # from GitLab, and won't have the `code` attribute
            # we use the req.status_code instead in that case
            error_status = getattr(e, "code", req.status_code)
            self.logger.info(
                "gitlab.refresh-identity-failure",
                extra={
                    "identity_id": identity.id,
                    "error_status": error_status,
                    "error_message": str(e),
                },
            )
            payload = {}

        self.handle_refresh_error(req, payload)

        identity.data.update(get_oauth_data(payload))
        identity.update(data=identity.data)
        return identity
コード例 #20
0
ファイル: provider.py プロジェクト: tsl0922/sentry-wxwork
    def refresh_identity(self, auth_identity):
        url = '%s?corpid=%s&corpsecret=%s' % (
            self.access_token_url, self.client_id, self.client_secret)
        response = safe_urlopen(url)
        self.logger.debug('Response code: %s, content: %s' %
                          (response.status_code, response.content))
        data = json.loads(response.content)

        if data['errcode'] != 0:
            raise IdentityNotValid('errcode: %d, errmsg: %s'
                                   & (data['errcode'], data['errmsg']))

        auth_identity.data.update(self.get_identity_data(data))
        auth_identity.update(data=auth_identity.data)
コード例 #21
0
ファイル: oauth2.py プロジェクト: vladborovtsov/sentry
    def refresh_identity(self, identity, *args, **kwargs):
        refresh_token = identity.data.get("refresh_token")

        if not refresh_token:
            raise IdentityNotValid("Missing refresh token")

        # XXX(meredith): This is used in VSTS's `get_refresh_token_params`
        kwargs["identity"] = identity
        data = self.get_refresh_token_params(refresh_token, *args, **kwargs)

        req = safe_urlopen(
            url=self.get_refresh_token_url(), headers=self.get_refresh_token_headers(), data=data
        )

        try:
            body = safe_urlread(req)
            payload = json.loads(body)
        except Exception:
            payload = {}

        self.handle_refresh_error(req, payload)

        identity.data.update(self.get_oauth_data(payload))
        return identity.update(data=identity.data)
コード例 #22
0
ファイル: saml2.py プロジェクト: saldanac/sentry
    def dispatch(self, request, organization_slug):
        if request.method != 'POST':
            return HttpResponseNotAllowed(['POST'])

        provider = get_provider(organization_slug)
        if provider is None:
            messages.add_message(request, messages.ERROR, ERR_NO_SAML_SSO)
            return HttpResponseRedirect('/')

        organization = Organization.objects.get(slug=organization_slug)
        saml_config = provider.build_saml_config(organization_slug)

        auth = provider.build_auth(request, saml_config)
        auth.process_response()
        errors = auth.get_errors()
        if errors:
            error_reason = auth.get_last_error_reason()
            raise IdentityNotValid(error_reason)

        attributes = auth.get_attributes()
        nameid = auth.get_nameid()

        email = self.retrieve_email(attributes, nameid, provider.config)
        user_emails = list(
            UserEmail.objects.filter(email__iexact=email,
                                     is_verified=True).order_by('id'))

        users = []
        if user_emails:
            users = User.objects.filter(
                id__in=set((ue.user_id for ue in user_emails)),
                is_active=True,
                sentry_orgmember_set__organization_id=organization.id)
            users = list(users[0:2])

        if not users:
            options_jit = provider.config.get('options',
                                              {}).get('options_jit', False)

            if not options_jit:
                message = "The user with a verified email %s does not exist" % email
                return HttpResponseServerError(message)
            else:
                return HttpResponseServerError(
                    "Just-in-Time provisioning not implemented yet")

        if len(users) > 1:
            return HttpResponseServerError(
                "Found several accounts related with %s on this organization" %
                email)

        user = users[0]
        user.backend = settings.AUTHENTICATION_BACKENDS[0]

        login_resp = login(request,
                           user,
                           after_2fa=request.build_absolute_uri(),
                           organization_id=organization.id)

        if login_resp:
            request.session['saml'] = {
                'nameid': nameid,
                'nameid_format': auth.get_nameid_format(),
                'session_index': auth.get_session_index()
            }

        return HttpResponseRedirect(get_login_redirect(request))