def handle_auth_required(self, request, *args, **kwargs): auth.initiate_login(request, next_url=request.get_full_path()) if "organization_slug" in kwargs: redirect_to = reverse("sentry-auth-organization", args=[kwargs["organization_slug"]]) else: redirect_to = auth.get_login_url() return self.redirect(redirect_to)
def handle_auth_required(self, request, *args, **kwargs): auth.initiate_login(request, next_url=request.get_full_path()) if "organization_slug" in kwargs: redirect_to = reverse("sentry-auth-organization", args=[kwargs["organization_slug"]]) else: redirect_to = auth.get_login_url() return self.redirect(redirect_to, headers={"X-Robots-Tag": "noindex, nofollow"})
def get(self, request, *args, **kwargs): """ Get context required to show a login page. Registration is handled elsewhere. """ if request.user.is_authenticated: # if the user is a superuser, but not 'superuser authenticated' we # allow them to re-authenticate to gain superuser status if not request.user.is_superuser or is_active_superuser(request): return self.respond_authenticated(request) next_uri = self.get_next_uri(request) # we always reset the state on GET so you don't end up at an odd location auth.initiate_login(request, next_uri) # Auth login verifies the test cookie is set request.session.set_test_cookie() # Single org mode -- send them to the org-specific handler if settings.SENTRY_SINGLE_ORGANIZATION: org = Organization.get_default() return Response({ "nextUri": reverse("sentry-auth-organization", args=[org.slug]) }) session_expired = "session_expired" in request.COOKIES payload = self.prepare_login_context(request, *args, **kwargs) response = Response(payload) if session_expired: response.delete_cookie("session_expired") return response
def handle_auth_required(self, request, *args, **kwargs): auth.initiate_login(request, next_url=request.get_full_path()) if 'organization_slug' in kwargs: redirect_to = reverse('sentry-auth-organization', args=[kwargs['organization_slug']]) else: redirect_to = auth.get_login_url() return self.redirect(redirect_to, headers={'X-Robots-Tag': 'noindex, nofollow'})
def wrapped(request, *args, **kwargs): if not is_active_superuser(request): if request.user.is_superuser: auth.initiate_login(request, next_url=request.get_full_path()) return HttpResponseRedirect(auth.get_login_url()) return render_to_response('sentry/missing_permissions.html', {}, request, status=400) return func(request, *args, **kwargs)
def get(self, request, *args, **kwargs): next_uri = self.get_next_uri(request, *args, **kwargs) if request.user.is_authenticated(): # if the user is a superuser, but not 'superuser authenticated' # we allow them to re-authenticate to gain superuser status if not request.user.is_superuser or is_active_superuser(request): return self.handle_authenticated(request, *args, **kwargs) request.session.set_test_cookie() # we always reset the state on GET so you dont end up at an odd location auth.initiate_login(request, next_uri) # Single org mode -- send them to the org-specific handler if settings.SENTRY_SINGLE_ORGANIZATION: org = Organization.get_default() next_uri = reverse('sentry-auth-organization', args=[org.slug]) return HttpResponseRedirect(next_uri) session_expired = 'session_expired' in request.COOKIES if session_expired: messages.add_message(request, messages.WARNING, WARN_SESSION_EXPIRED) response = self.handle_basic_auth(request, *args, **kwargs) if session_expired: response.delete_cookie('session_expired') return response
def get(self, request, **kwargs): next_uri = self.get_next_uri(request) if request.user.is_authenticated(): # if the user is a superuser, but not 'superuser authenticated' # we allow them to re-authenticate to gain superuser status if not request.user.is_superuser or is_active_superuser(request): return self.handle_authenticated(request) request.session.set_test_cookie() # we always reset the state on GET so you dont end up at an odd location auth.initiate_login(request, next_uri) # Single org mode -- send them to the org-specific handler if settings.SENTRY_SINGLE_ORGANIZATION: org = Organization.get_default() next_uri = reverse("sentry-auth-organization", args=[org.slug]) return HttpResponseRedirect(next_uri) session_expired = "session_expired" in request.COOKIES if session_expired: messages.add_message(request, messages.WARNING, WARN_SESSION_EXPIRED) response = self.handle_basic_auth(request, **kwargs) if session_expired: response.delete_cookie("session_expired") return response
def get(self, request, member_id, token): try: helper = self.get_helper(request, member_id, token) except OrganizationMember.DoesNotExist: return self.respond_invalid(request) if not helper.member_pending or not helper.valid_token: return self.respond_invalid(request) om = helper.om organization = om.organization # Keep track of the invite email for when we land back on the login page request.session["invite_email"] = om.email try: auth_provider = AuthProvider.objects.get(organization=organization) except AuthProvider.DoesNotExist: auth_provider = None data = { "orgSlug": organization.slug, "needsAuthentication": not helper.user_authenticated, "needs2fa": helper.needs_2fa, "needsSso": auth_provider is not None, # If they're already a member of the organization its likely # they're using a shared account and either previewing this invite # or are incorrectly expecting this to create a new account. "existingMember": helper.member_already_exists, } response = Response(None) # Allow users to register an account when accepting an invite if not helper.user_authenticated: request.session["can_register"] = True add_invite_cookie(request, response, member_id, token) # When SSO is required do *not* set a next_url to return to accept # invite. The invite will be accepted after SSO is completed. url = (reverse("sentry-accept-invite", args=[member_id, token]) if not auth_provider else "/") auth.initiate_login(self.request, next_url=url) # If the org has SSO setup, we'll store the invite cookie to later # associate the org member after authentication. We can avoid needing # to come back to the accept invite page since 2FA will *not* be # required if SSO is required. if auth_provider is not None: add_invite_cookie(request, response, member_id, token) provider = auth_provider.get_provider() data["ssoProvider"] = provider.name if helper.needs_2fa: add_invite_cookie(request, response, member_id, token) response.data = data return response
def handle_auth_required(self, request, *args, **kwargs): from sentry.utils import auth # Django 1.9 setup issue auth.initiate_login(request, next_url=request.get_full_path()) if 'organization_slug' in kwargs: redirect_to = reverse('sentry-auth-organization', args=[kwargs['organization_slug']]) else: redirect_to = auth.get_login_url() return self.redirect(redirect_to)
def wrapped(request, *args, **kwargs): if not request.user.is_authenticated(): auth.initiate_login(request, next_url=request.get_full_path()) if 'organization_slug' in kwargs: redirect_uri = reverse('sentry-auth-organization', args=[kwargs['organization_slug']]) else: redirect_uri = auth.get_login_url() return HttpResponseRedirect(redirect_uri) return func(request, *args, **kwargs)
def wrapped(request, *args, **kwargs): if not request.user.is_authenticated(): auth.initiate_login(request, next_url=request.get_full_path()) if "organization_slug" in kwargs: redirect_uri = reverse("sentry-auth-organization", args=[kwargs["organization_slug"]]) else: redirect_uri = auth.get_login_url() return HttpResponseRedirect(redirect_uri) return func(request, *args, **kwargs)
def handle_permission_required(self, request, organization, *args, **kwargs): if self.needs_sso(request, organization): logger.info( "access.must-sso", extra={"organization_id": organization.id, "user_id": request.user.id}, ) auth.initiate_login(request, next_url=request.get_full_path()) redirect_uri = reverse("sentry-auth-organization", args=[organization.slug]) else: redirect_uri = self.get_no_permission_url(request, *args, **kwargs) return self.redirect(redirect_uri)
def handle_permission_required(self, request, organization, *args, **kwargs): if self.needs_sso(request, organization): logger.info('access.must-sso', extra={ 'organization_id': organization.id, 'user_id': request.user.id, }) auth.initiate_login(request, next_url=request.get_full_path()) redirect_uri = reverse('sentry-auth-organization', args=[organization.slug]) else: redirect_uri = self.get_no_permission_url(request, *args, **kwargs) return self.redirect(redirect_uri)
def handle_permission_required(self, request, organization, *args, **kwargs): from sentry.utils import auth # Django 1.9 setup issue if self.needs_sso(request, organization): logger.info('access.must-sso', extra={ 'organization_id': organization.id, 'user_id': request.user.id, }) auth.initiate_login(request, next_url=request.get_full_path()) redirect_uri = reverse('sentry-auth-organization', args=[organization.slug]) else: redirect_uri = self.get_no_permission_url(request, *args, **kwargs) return self.redirect(redirect_uri)
def handle_permission_required(self, request, organization, *args, **kwargs): needs_link = ( organization and request.user.is_authenticated() and self.valid_sso_required and not request.access.sso_is_valid ) auth.initiate_login(request, next_url=request.get_full_path()) if needs_link: messages.add_message(request, messages.ERROR, ERR_MISSING_SSO_LINK) redirect_uri = reverse("sentry-auth-organization", args=[organization.slug]) else: redirect_uri = self.get_no_permission_url(request, *args, **kwargs) return self.redirect(redirect_uri)
def get(self, request, member_id, token): try: helper = self.get_helper(request, member_id, token) except OrganizationMember.DoesNotExist: return self.respond_invalid(request) if not helper.member_pending or not helper.valid_token: return self.respond_invalid(request) om = helper.om organization = om.organization # Keep track of the invite email for when we land back on the login page request.session["invite_email"] = om.email try: auth_provider = AuthProvider.objects.get(organization=organization) except AuthProvider.DoesNotExist: auth_provider = None data = { "orgSlug": organization.slug, "needsAuthentication": not helper.user_authenticated, "needs2fa": helper.needs_2fa, "needsSso": auth_provider is not None, # If they're already a member of the organization its likely # they're using a shared account and either previewing this invite # or are incorrectly expecting this to create a new account. "existingMember": helper.member_already_exists, } if auth_provider is not None: provider = auth_provider.get_provider() data["ssoProvider"] = provider.name # Allow users to register an account when accepting an invite if not helper.user_authenticated: url = reverse("sentry-accept-invite", args=[member_id, token]) auth.initiate_login(self.request, next_url=url) request.session["can_register"] = True response = Response(data) if helper.needs_2fa: helper.add_invite_cookie(request, response, member_id, token) return response
def handle_permission_required(self, request, organization, *args, **kwargs): needs_link = ( organization and request.user.is_authenticated() and self.valid_sso_required and not request.access.sso_is_valid ) auth.initiate_login(request, next_url=request.get_full_path()) if needs_link: messages.add_message( request, messages.ERROR, ERR_MISSING_SSO_LINK, ) redirect_uri = reverse('sentry-auth-organization', args=[organization.slug]) else: redirect_uri = self.get_no_permission_url(request, *args, **kwargs) return self.redirect(redirect_uri)
def handle(self, request): next_uri = request.GET.get(REDIRECT_FIELD_NAME, None) if request.user.is_authenticated(): if auth.is_valid_redirect(next_uri, host=request.get_host()): return self.redirect(next_uri) return self.redirect_to_org(request) request.session.set_test_cookie() if next_uri: auth.initiate_login(request, next_uri) # Single org mode -- send them to the org-specific handler if settings.SENTRY_SINGLE_ORGANIZATION: org = Organization.get_default() next_uri = reverse('sentry-auth-organization', args=[org.slug]) return HttpResponseRedirect(next_uri) op = request.POST.get('op') if op == 'sso' and request.POST.get('organization'): auth_provider = self.get_auth_provider( request.POST['organization']) if auth_provider: next_uri = reverse('sentry-auth-organization', args=[request.POST['organization']]) else: next_uri = request.path messages.add_message(request, messages.ERROR, ERR_NO_SSO) return HttpResponseRedirect(next_uri) session_expired = 'session_expired' in request.COOKIES if session_expired: messages.add_message(request, messages.WARNING, WARN_SESSION_EXPIRED) response = self.handle_basic_auth(request) if session_expired: response.delete_cookie('session_expired') return response
def handle(self, request): next_uri = request.GET.get('next', None) if request.user.is_authenticated(): if auth.is_valid_redirect(next_uri): return self.redirect(next_uri) return self.redirect_to_org(request) request.session.set_test_cookie() if next_uri: auth.initiate_login(request, next_uri) # Single org mode -- send them to the org-specific handler if settings.SENTRY_SINGLE_ORGANIZATION: org = Organization.get_default() next_uri = reverse('sentry-auth-organization', args=[org.slug]) return HttpResponseRedirect(next_uri) op = request.POST.get('op') if op == 'sso' and request.POST.get('organization'): auth_provider = self.get_auth_provider(request.POST['organization']) if auth_provider: next_uri = reverse('sentry-auth-organization', args=[request.POST['organization']]) else: next_uri = request.path messages.add_message(request, messages.ERROR, ERR_NO_SSO) return HttpResponseRedirect(next_uri) session_expired = 'session_expired' in request.COOKIES if session_expired: messages.add_message(request, messages.WARNING, WARN_SESSION_EXPIRED) response = self.handle_basic_auth(request) if session_expired: response.delete_cookie('session_expired') return response
def handle(self, request, member_id, token): assert request.method in ('POST', 'GET') try: helper = WebInviteHelper( instance=self, request=request, member_id=member_id, token=token ) except OrganizationMember.DoesNotExist: return self.redirect_with_err_message(request) if not helper.member_pending or not helper.valid_token: return self.redirect_with_err_message(request) om = helper.om organization = om.organization qs = Project.objects.filter( organization=organization, ) project_list = list(qs[:25]) project_count = qs.count() context = { 'org_name': organization.name, 'project_list': project_list, 'project_count': project_count, 'needs_authentication': not helper.user_authenticated, 'needs_2fa': helper.needs_2fa, 'logout_url': u'{}?next={}'.format( reverse('sentry-logout'), request.path, ), 'login_url': u'{}?next={}'.format( reverse('sentry-login'), request.path, ), 'register_url': u'{}?next={}'.format( reverse('sentry-register'), request.path, ), } if not helper.user_authenticated: # Show login or register form auth.initiate_login(request, next_url=request.get_full_path()) request.session['can_register'] = True request.session['invite_email'] = om.email return self.respond('sentry/accept-organization-invite.html', context) if helper.needs_2fa: # redirect to setup 2fa response = self.respond('sentry/accept-organization-invite.html', context) response.set_cookie(PENDING_INVITE, request.path, max_age=MAX_AGE) return response # if they're already a member of the organization its likely they're # using a shared account and either previewing this invite or # are incorrectly expecting this to create a new account for them context['existing_member'] = helper.member_already_exists form = self.get_form(request) if form.is_valid(): helper.accept_invite() request.session.pop('can_register', None) response = self.redirect(reverse('sentry-organization-home', args=[organization.slug])) return helper.remove_invite_cookie(response) context['form'] = form return self.respond('sentry/accept-organization-invite.html', context)
def put(self, request: Request): """ Verify a User ````````````` This endpoint verifies the currently authenticated user (for example, to gain superuser). :auth: required """ if not request.user.is_authenticated: return Response(status=status.HTTP_401_UNAUTHORIZED) validator = AuthVerifyValidator(data=request.data) if not validator.is_valid(): return self.respond(validator.errors, status=status.HTTP_400_BAD_REQUEST) authenticated = False # See if we have a u2f challenge/response if "challenge" in validator.validated_data and "response" in validator.validated_data: try: interface = Authenticator.objects.get_interface( request.user, "u2f") if not interface.is_enrolled(): raise LookupError() challenge = json.loads(validator.validated_data["challenge"]) response = json.loads(validator.validated_data["response"]) can_webauthn_signin = self.check_can_webauthn_signin( request.user, request.user) authenticated = interface.validate_response( request, challenge, response, can_webauthn_signin) except ValueError: pass except LookupError: pass # attempt password authentication else: authenticated = request.user.check_password( validator.validated_data["password"]) # UI treats 401s by redirecting, this 401 should be ignored if not authenticated: return Response({"detail": { "code": "ignore" }}, status=status.HTTP_403_FORBIDDEN) try: # Must use the real request object that Django knows about auth.login(request._request, request.user) except auth.AuthUserPasswordExpired: return Response( { "code": "password-expired", "message": "Cannot sign-in with basic auth because password has expired.", }, status=status.HTTP_403_FORBIDDEN, ) if request.user.is_superuser and not is_active_superuser( request) and Superuser.org_id: # if a superuser hitting this endpoint is not active, they are most likely # trying to become active, and likely need to re-identify with SSO to do so. redirect = request.META.get("HTTP_REFERER", "") if not is_safe_url(redirect, allowed_hosts=(request.get_host(), )): redirect = None initiate_login(request, redirect) raise SsoRequired( Organization.objects.get_from_cache(id=Superuser.org_id)) request.user = request._request.user return self.get(request)
def handle(self, request, member_id, token): assert request.method in ('POST', 'GET') try: om = OrganizationMember.objects.get(pk=member_id) except OrganizationMember.DoesNotExist: messages.add_message( request, messages.ERROR, ERR_INVITE_INVALID, ) return self.redirect(reverse('sentry')) if not om.is_pending: messages.add_message( request, messages.ERROR, ERR_INVITE_INVALID, ) return self.redirect(reverse('sentry')) if not constant_time_compare(om.token or om.legacy_token, token): messages.add_message( request, messages.ERROR, ERR_INVITE_INVALID, ) return self.redirect(reverse('sentry')) organization = om.organization qs = Project.objects.filter( organization=organization, ) project_list = list(qs.select_related('team')[:25]) project_count = qs.count() context = { 'organization': om.organization, 'project_list': project_list, 'project_count': project_count, 'needs_authentication': not request.user.is_authenticated(), 'logout_url': '{}?next={}'.format( reverse('sentry-logout'), request.path, ), 'login_url': '{}?next={}'.format( reverse('sentry-login'), request.path, ), 'register_url': '{}?next={}'.format( reverse('sentry-register'), request.path, ), } if not request.user.is_authenticated(): # Show login or register form auth.initiate_login(request, next_url=request.get_full_path()) request.session['can_register'] = True request.session['invite_email'] = om.email return self.respond('sentry/accept-organization-invite.html', context) # if they're already a member of the organization its likely they're # using a shared account and either previewing this invite or # are incorrectly expecting this to create a new account for them context['existing_member'] = OrganizationMember.objects.filter( user=request.user.id, organization=om.organization_id, ).exists() form = self.get_form(request) if form.is_valid(): if OrganizationMember.objects.filter(organization=organization, user=request.user).exists(): messages.add_message( request, messages.SUCCESS, _('You are already a member of the %r organization.') % ( organization.name.encode('utf-8'), ) ) om.delete() else: om.user = request.user om.email = None om.save() self.create_audit_entry( request, organization=organization, target_object=om.id, target_user=request.user, event=AuditLogEntryEvent.MEMBER_ACCEPT, data=om.get_audit_log_data(), ) messages.add_message( request, messages.SUCCESS, _('You have been added to the %r organization.') % ( organization.name.encode('utf-8'), ) ) member_joined.send(member=om, sender=self) request.session.pop('can_register', None) return self.redirect(reverse('sentry-organization-home', args=[organization.slug])) context['form'] = form return self.respond('sentry/accept-organization-invite.html', context)
def handle(self, request, member_id, token): assert request.method in ('POST', 'GET') try: om = OrganizationMember.objects.get(pk=member_id) except OrganizationMember.DoesNotExist: messages.add_message( request, messages.ERROR, ERR_INVITE_INVALID, ) return self.redirect(reverse('sentry')) if not om.is_pending: messages.add_message( request, messages.ERROR, ERR_INVITE_INVALID, ) return self.redirect(reverse('sentry')) if not constant_time_compare(om.token or om.legacy_token, token): messages.add_message( request, messages.ERROR, ERR_INVITE_INVALID, ) return self.redirect(reverse('sentry')) organization = om.organization qs = Project.objects.filter(organization=organization, ) project_list = list(qs[:25]) project_count = qs.count() context = { 'organization': om.organization, 'project_list': project_list, 'project_count': project_count, 'needs_authentication': not request.user.is_authenticated(), 'logout_url': '{}?next={}'.format( reverse('sentry-logout'), request.path, ), 'login_url': '{}?next={}'.format( reverse('sentry-login'), request.path, ), 'register_url': '{}?next={}'.format( reverse('sentry-register'), request.path, ), } if not request.user.is_authenticated(): # Show login or register form auth.initiate_login(request, next_url=request.get_full_path()) request.session['can_register'] = True request.session['invite_email'] = om.email return self.respond('sentry/accept-organization-invite.html', context) # if they're already a member of the organization its likely they're # using a shared account and either previewing this invite or # are incorrectly expecting this to create a new account for them context['existing_member'] = OrganizationMember.objects.filter( user=request.user.id, organization=om.organization_id, ).exists() form = self.get_form(request) if form.is_valid(): if OrganizationMember.objects.filter(organization=organization, user=request.user).exists(): messages.add_message( request, messages.SUCCESS, _('You are already a member of the %r organization.') % (organization.name.encode('utf-8'), )) om.delete() else: om.user = request.user om.email = None om.save() self.create_audit_entry( request, organization=organization, target_object=om.id, target_user=request.user, event=AuditLogEntryEvent.MEMBER_ACCEPT, data=om.get_audit_log_data(), ) messages.add_message( request, messages.SUCCESS, _('You have been added to the %r organization.') % (organization.name.encode('utf-8'), )) member_joined.send(member=om, sender=self) request.session.pop('can_register', None) return self.redirect( reverse('sentry-organization-home', args=[organization.slug])) context['form'] = form return self.respond('sentry/accept-organization-invite.html', context)
def handle(self, request, member_id, token): assert request.method in ('POST', 'GET') try: helper = WebInviteHelper(instance=self, request=request, member_id=member_id, token=token) except OrganizationMember.DoesNotExist: return self.redirect_with_err_message(request) if not helper.member_pending or not helper.valid_token: return self.redirect_with_err_message(request) om = helper.om organization = om.organization context = { 'org_name': organization.name, 'needs_authentication': not helper.user_authenticated, 'needs_2fa': helper.needs_2fa, 'logout_url': u'{}?next={}'.format( reverse('sentry-logout'), request.path, ), 'login_url': u'{}?next={}'.format( reverse('sentry-login'), request.path, ), 'register_url': u'{}?next={}'.format( reverse('sentry-register'), request.path, ), } if not helper.user_authenticated: # Show login or register form auth.initiate_login(request, next_url=request.get_full_path()) request.session['can_register'] = True request.session['invite_email'] = om.email return self.respond('sentry/accept-organization-invite.html', context) if helper.needs_2fa: # redirect to setup 2fa response = self.respond('sentry/accept-organization-invite.html', context) response.set_cookie(PENDING_INVITE, request.path, max_age=COOKIE_MAX_AGE) return response # if they're already a member of the organization its likely they're # using a shared account and either previewing this invite or # are incorrectly expecting this to create a new account for them context['existing_member'] = helper.member_already_exists form = self.get_form(request) if form.is_valid(): helper.accept_invite() request.session.pop('can_register', None) response = self.redirect( reverse('sentry-organization-home', args=[organization.slug])) return helper.remove_invite_cookie(response) context['form'] = form return self.respond('sentry/accept-organization-invite.html', context)
def handle(self, request, member_id, token): assert request.method in ("POST", "GET") try: helper = WebInviteHelper(instance=self, request=request, member_id=member_id, token=token) except OrganizationMember.DoesNotExist: return self.redirect_with_err_message(request) if not helper.member_pending or not helper.valid_token: return self.redirect_with_err_message(request) om = helper.om organization = om.organization context = { "org_name": organization.name, "needs_authentication": not helper.user_authenticated, "needs_2fa": helper.needs_2fa, "logout_url": u"{}?next={}".format(reverse("sentry-logout"), request.path), "login_url": u"{}?next={}".format(reverse("sentry-login"), request.path), "register_url": u"{}?next={}".format(reverse("sentry-register"), request.path), } if not helper.user_authenticated: # Show login or register form auth.initiate_login(request, next_url=request.get_full_path()) request.session["can_register"] = True request.session["invite_email"] = om.email return self.respond("sentry/accept-organization-invite.html", context) if helper.needs_2fa: # redirect to setup 2fa response = self.respond("sentry/accept-organization-invite.html", context) response.set_cookie(PENDING_INVITE, request.path, max_age=COOKIE_MAX_AGE) return response # if they're already a member of the organization its likely they're # using a shared account and either previewing this invite or # are incorrectly expecting this to create a new account for them context["existing_member"] = helper.member_already_exists form = self.get_form(request) if form.is_valid(): helper.accept_invite() request.session.pop("can_register", None) response = self.redirect(organization.get_url()) return helper.remove_invite_cookie(response) context["form"] = form return self.respond("sentry/accept-organization-invite.html", context)