Repository: getredash/redash

Issue:
LDAP Auth /login_auth/login 404
<!--
#####################################################################
#
# Need support? USE THE FORUM! https://discuss.redash.io/c/support.
#
# Don't have steps to reproduce and actually not sure it's a bug?
# Use the forum! https://discuss.redash.io/c/support.
#
#####################################################################

**Got an idea for a new feature?** Check if it isn't on the roadmap already: http://bit.ly/redash-roadmap and start a new discussion in the features category: https://discuss.redash.io/c/feature-requests 🌟.

Found a bug? Please fill out the sections below... thank you 👍
-->

### Issue Summary

With LDAP auth enabled, app routes url to '/ldap/login' based on ldap_auth.py in authentication.
Template login page redirects to '/ldap_auth/login' which returns a 404 since there is no route pointing to that url. 

### Steps to Reproduce

1. enable LDAP auth
2. navigate to localhost and click link to SSO login page
3. observe 404

Fix: adjust route in /authentication/ldap_auth.py


### Technical details:

* Redash Version: redash.3.0.0.b3134
* Browser/OS: Chrome
* How did you install Redash: ami

Can't logout when using only Google Apps SSO
### Issue Summary

Trying to logout Redash keep redirecting me to the login page and signing me in automatically.

This happened on a fresh installation with the following settings, which I think that is somehow related with the issue:
- **REDASH_GOOGLE_APPS_DOMAINS**: "domain1.com,gmail.com"
- **REDASH_PASSWORD_LOGIN_ENABLED**: "false"

---

the logs:

```
[2016-08-26 03:32:45,014][PID:25][INFO][metrics] method=GET path=/logout endpoint=redash.logout status=302 content_type=text/html; charset=utf-8 content_length=237 duration=6.48 query_count=2 query_duration=2.41
[2016-08-26 03:32:45,016][PID:25][INFO][metrics] method=GET path=/logout endpoint=redash.logout status=500 content_type=? content_length=-1 duration=8.56 query_count=2 query_duration=2.41
[2016-08-26 03:32:45,163][PID:25][INFO][metrics] method=GET path=/login endpoint=redash.login status=302 content_type=text/html; charset=utf-8 content_length=251 duration=2.97 query_count=0 query_duration=0.00
[2016-08-26 03:32:45,165][PID:25][INFO][metrics] method=GET path=/login endpoint=redash.login status=500 content_type=? content_length=-1 duration=5.24 query_count=0 query_duration=0.00
[2016-08-26 03:32:45,438][PID:25][INFO][metrics] method=GET path=/oauth/google endpoint=google_oauth.authorize status=302 content_type=text/html; charset=utf-8 content_length=941 duration=2.95 query_count=0 query_duration=0.00
[2016-08-26 03:32:45,440][PID:25][INFO][metrics] method=GET path=/oauth/google endpoint=google_oauth.authorize status=500 content_type=? content_length=-1 duration=5.40 query_count=0 query_duration=0.00
[2016-08-26 03:32:46,375][PID:25][INFO][requests.packages.urllib3.connectionpool] Starting new HTTPS connection (1): www.googleapis.com
[2016-08-26 03:32:46,634][PID:25][INFO][metrics] method=GET path=/oauth/google_callback endpoint=google_oauth.callback status=302 content_type=text/html; charset=utf-8 content_length=209 duration=494.07 query_count=6 query_duration=3.87
[2016-08-26 03:32:46,637][PID:25][INFO][metrics] method=GET path=/oauth/google_callback endpoint=google_oauth.callback status=500 content_type=? content_length=-1 duration=496.63 query_count=6 query_duration=3.87
[2016-08-26 03:32:46,789][PID:30][INFO][metrics] method=GET path=/ endpoint=redash.index status=200 content_type=text/html; charset=utf-8 content_length=3420 duration=8.75 query_count=4 query_duration=3.33
[2016-08-26 03:32:46,791][PID:30][INFO][metrics] method=GET path=/ endpoint=redash.index status=500 content_type=? content_length=-1 duration=10.59 query_count=4 query_duration=3.33
[2016-08-26 03:32:48,043][PID:30][INFO][metrics] method=GET path=/api/dashboards endpoint=dashboards status=200 content_type=application/json content_length=2 duration=11.50 query_count=5 query_duration=5.29
[2016-08-26 03:32:48,045][PID:30][INFO][metrics] method=GET path=/api/dashboards endpoint=dashboards status=500 content_type=? content_length=-1 duration=13.32 query_count=5 query_duration=5.29
[2016-08-26 03:32:48,222][PID:30][INFO][metrics] method=GET path=/api/queries/recent endpoint=recent_queries status=200 content_type=application/json content_length=2 duration=14.51 query_count=5 query_duration=7.75
[2016-08-26 03:32:48,225][PID:30][INFO][metrics] method=GET path=/api/queries/recent endpoint=recent_queries status=500 content_type=? content_length=-1 duration=17.70 query_count=5 query_duration=7.75
[2016-08-26 03:32:48,226][PID:25][INFO][metrics] method=GET path=/api/dashboards/recent endpoint=recent_dashboards status=200 content_type=application/json content_length=2 duration=15.83 query_count=7 query_duration=7.64
[2016-08-26 03:32:48,228][PID:25][INFO][metrics] method=GET path=/api/dashboards/recent endpoint=recent_dashboards status=500 content_type=? content_length=-1 duration=18.15 query_count=7 query_duration=7.64
[2016-08-26 03:32:49,253][PID:32][INFO][metrics] method=POST path=/api/events endpoint=events status=200 content_type=application/json content_length=4 duration=9.48 query_count=3 query_duration=2.62
[2016-08-26 03:32:49,255][PID:32][INFO][metrics] method=POST path=/api/events endpoint=events status=500 content_type=? content_length=-1 duration=11.85 query_count=3 query_duration=2.62
```

---
- Redash Version: 0.12.0-rc
- Browser/OS: Chrome Incognito Mode
- How did you install Redash: docker



Discussion:
This seems fixed in beta version 4, but should still be addressed in v3
I don't think it was fixed in v4, but will try to fix it in one of the next updates of v4.

We won't release a patch release for v3 for this bug, but you can patch your version by replacing `ldap_auth/login` with `ldap/login` in the templates. 
It stopped when I removed the google cookie. 

What happens is:
1. You logout, and redirected to `/login`.
2. Because you have only Google Apps enabled, it redirects to Google Apps for authentication.
3. As you already authorized Redash, it redirects back to Redash and logs you in.

What we can do (should do?) is show you the login page with the Google Apps button instead of automatic redirect.

If you enable password based login, this is what will happen.

I think that we should do this. Because sometimes you want to outsource the user management by  disabling `REDASH_PASSWORD_LOGIN_ENABLED` and allowing only Google Apps Login. So if we want to disable an user from accessing Redash we just need to deactivate the google account.


Resolving patch:
diff --git a/redash/authentication/saml_auth.py b/redash/authentication/saml_auth.py
--- a/redash/authentication/saml_auth.py
+++ b/redash/authentication/saml_auth.py
@@ -20,7 +20,7 @@ def get_saml_client(org):
     """
     metadata_url = org.get_setting("auth_saml_metadata_url")
     entity_id = org.get_setting("auth_saml_entity_id")
-    acs_url = url_for("saml_auth.idp_initiated", _external=True)
+    acs_url = url_for("saml_auth.idp_initiated", org_slug=org.slug, _external=True)
 
     saml_settings = {
         'metadata': {
@@ -61,10 +61,10 @@ def get_saml_client(org):
 
 
 @blueprint.route(org_scoped_rule('/saml/callback'), methods=['POST'])
-def idp_initiated():
+def idp_initiated(org_slug=None):
     if not current_org.get_setting("auth_saml_enabled"):
         logger.error("SAML Login is not enabled")
-        return redirect(url_for('redash.index'))
+        return redirect(url_for('redash.index', org_slug=org_slug))
 
     saml_client = get_saml_client(current_org)
     authn_response = saml_client.parse_authn_request_response(
@@ -84,16 +84,16 @@ def idp_initiated():
         group_names = authn_response.ava.get('RedashGroups')
         user.update_group_assignments(group_names)
 
-    url = url_for('redash.index')
+    url = url_for('redash.index', org_slug=org_slug)
 
     return redirect(url)
 
 
 @blueprint.route(org_scoped_rule("/saml/login"))
-def sp_initiated():
+def sp_initiated(org_slug=None):
     if not current_org.get_setting("auth_saml_enabled"):
         logger.error("SAML Login is not enabled")
-        return redirect(url_for('redash.index'))
+        return redirect(url_for('redash.index', org_slug=org_slug))
 
     saml_client = get_saml_client(current_org)
     nameid_format = current_org.get_setting('auth_saml_nameid_format')
diff --git a/redash/handlers/authentication.py b/redash/handlers/authentication.py
--- a/redash/handlers/authentication.py
+++ b/redash/handlers/authentication.py
@@ -111,16 +111,6 @@ def login(org_slug=None):
     if current_user.is_authenticated:
         return redirect(next_path)
 
-    if not current_org.get_setting('auth_password_login_enabled'):
-        if settings.REMOTE_USER_LOGIN_ENABLED:
-            return redirect(url_for("remote_user_auth.login", next=next_path))
-        elif current_org.get_setting('auth_saml_enabled'):  # settings.SAML_LOGIN_ENABLED:
-            return redirect(url_for("saml_auth.sp_initiated", next=next_path))
-        elif settings.LDAP_LOGIN_ENABLED:
-            return redirect(url_for("ldap_auth.login", next=next_path))
-        else:
-            return redirect(get_google_auth_url(next_path))
-
     if request.method == 'POST':
         try:
             org = current_org._get_current_object()
@@ -142,6 +132,7 @@ def login(org_slug=None):
                            email=request.form.get('email', ''),
                            show_google_openid=settings.GOOGLE_OAUTH_ENABLED,
                            google_auth_url=google_auth_url,
+                           show_password_login=current_org.get_setting('auth_password_login_enabled'),
                            show_saml_login=current_org.get_setting('auth_saml_enabled'),
                            show_remote_user_login=settings.REMOTE_USER_LOGIN_ENABLED,
                            show_ldap_login=settings.LDAP_LOGIN_ENABLED)
diff --git a/redash/handlers/organization.py b/redash/handlers/organization.py
--- a/redash/handlers/organization.py
+++ b/redash/handlers/organization.py
@@ -9,7 +9,6 @@
 
 
 @routes.route(org_scoped_rule('/api/organization/status'), methods=['GET'])
-@require_admin
 @login_required
 def organization_status(org_slug=None):
     counters = {


Test patch:
diff --git a/tests/test_handlers.py b/tests/test_handlers.py
--- a/tests/test_handlers.py
+++ b/tests/test_handlers.py
@@ -83,14 +83,6 @@ def setUpClass(cls):
     def tearDownClass(cls):
         settings.ORG_RESOLVING = "multi_org"
 
-    def test_redirects_to_google_login_if_password_disabled(self):
-        self.factory.org.set_setting('auth_password_login_enabled', False)
-        with self.app.test_request_context('/default/login'):
-            rv = self.client.get('/default/login')
-            self.assertEquals(rv.status_code, 302)
-            self.assertTrue(rv.location.endswith(url_for('google_oauth.authorize', next='/default/')))
-        self.factory.org.set_setting('auth_password_login_enabled', True)
-
     def test_get_login_form(self):
         rv = self.client.get('/default/login')
         self.assertEquals(rv.status_code, 200)