Repository: Kinto/kinto

Issue:
Kinto onboarding experience (part 2)
These is a followup from #1733 with random feedback with onboarding when trying to use the [accounts plugin](http://docs.kinto-storage.org/en/stable/api/1.x/accounts.html).



Started with updating my `config/kinto.ini` with:

```
kinto.includes = kinto.plugins.default_bucket
                 kinto.plugins.admin
                 kinto.plugins.accounts
```

Restarting the server goes smoothly. The admin loads fine and renders a new entry for *Kinto Account Auth*. I never created any Account just yet, though out of curiosity I try to log in using silly:silly:

![](https://i.imgur.com/0OTeatP.png)

Tadaa:

![](https://i.imgur.com/7UMpDFv.png)

Wait, what?

Oh. It seems it actually used the Basic Auth strategy instead of the account one for login. This is odd and confusing as fsck.

Actually, I didn't went further with toying around with the admin as it looks broken to me. This is a little sad.
Kinto onboarding experience (part 2)
These is a followup from #1733 with random feedback with onboarding when trying to use the [accounts plugin](http://docs.kinto-storage.org/en/stable/api/1.x/accounts.html).



Started with updating my `config/kinto.ini` with:

```
kinto.includes = kinto.plugins.default_bucket
                 kinto.plugins.admin
                 kinto.plugins.accounts
```

Restarting the server goes smoothly. The admin loads fine and renders a new entry for *Kinto Account Auth*. I never created any Account just yet, though out of curiosity I try to log in using silly:silly:

![](https://i.imgur.com/0OTeatP.png)

Tadaa:

![](https://i.imgur.com/7UMpDFv.png)

Wait, what?

Oh. It seems it actually used the Basic Auth strategy instead of the account one for login. This is odd and confusing as fsck.

Actually, I didn't went further with toying around with the admin as it looks broken to me. This is a little sad.


Discussion:
You are right this is not supposed to happen! 

So, basically the issue here is:
* the `account` capability is exposed since the plugin was enabled
* the configured policies don't mention `account` in the `multiauth.policies` 
* the Kinto Admin thinks the server can authenticate users with account, where it can't.

I think the solution to this is would be to raise a configuration error if the account plugin is included but the policy is not enabled in `multiauth.policies` setting as described in the docs https://kinto.readthedocs.io//en/stable/api/1.x/accounts.html

You are right this is not supposed to happen! 

So, basically the issue here is:
* the `account` capability is exposed since the plugin was enabled
* the configured policies don't mention `account` in the `multiauth.policies` 
* the Kinto Admin thinks the server can authenticate users with account, where it can't.

I think the solution to this is would be to raise a configuration error if the account plugin is included but the policy is not enabled in `multiauth.policies` setting as described in the docs https://kinto.readthedocs.io//en/stable/api/1.x/accounts.html


Resolving patch:
diff --git a/kinto/plugins/accounts/__init__.py b/kinto/plugins/accounts/__init__.py
--- a/kinto/plugins/accounts/__init__.py
+++ b/kinto/plugins/accounts/__init__.py
@@ -1,9 +1,13 @@
+import re
+
 from kinto.authorization import PERMISSIONS_INHERITANCE_TREE
 from pyramid.exceptions import ConfigurationError
 
 ACCOUNT_CACHE_KEY = 'accounts:{}:verified'
 ACCOUNT_POLICY_NAME = 'account'
 
+DOCS_URL = "https://kinto.readthedocs.io/en/stable/api/1.x/accounts.html"
+
 
 def includeme(config):
     config.add_api_capability(
@@ -21,13 +25,28 @@ def includeme(config):
         'read': {'account': ['write', 'read']}
     }
 
-    # Add some safety to avoid weird behaviour with basicauth default policy.
     settings = config.get_settings()
+
+    # Check that the account policy is mentioned in config if included.
+    accountClass = 'AccountsAuthenticationPolicy'
+    policy = None
+    for k, v in settings.items():
+        m = re.match('multiauth\.policy\.(.*)\.use', k)
+        if m:
+            if v.endswith(accountClass):
+                policy = m.group(1)
+
+    if not policy:
+        error_msg = ("Account policy missing the 'multiauth.policy.*.use' "
+                     "setting. See {} in docs {}.").format(accountClass, DOCS_URL)
+        raise ConfigurationError(error_msg)
+
+    # Add some safety to avoid weird behaviour with basicauth default policy.
     auth_policies = settings['multiauth.policies']
-    if 'basicauth' in auth_policies and 'account' in auth_policies:
-        if auth_policies.index('basicauth') < auth_policies.index('account'):
-            error_msg = ("'basicauth' should not be mentioned before 'account' "
-                         "in 'multiauth.policies' setting.")
+    if 'basicauth' in auth_policies and policy in auth_policies:
+        if auth_policies.index('basicauth') < auth_policies.index(policy):
+            error_msg = ("'basicauth' should not be mentioned before '%s' "
+                         "in 'multiauth.policies' setting.") % policy
             raise ConfigurationError(error_msg)
 
     # We assume anyone in account_create_principals is to create


Test patch:
diff --git a/tests/plugins/test_accounts.py b/tests/plugins/test_accounts.py
--- a/tests/plugins/test_accounts.py
+++ b/tests/plugins/test_accounts.py
@@ -25,6 +25,17 @@ def get_app_settings(cls, extras=None):
         return super().get_app_settings(extras)
 
 
+class BadAccountsConfigTest(support.BaseWebTest, unittest.TestCase):
+
+    def test_raise_configuration_if_accounts_not_mentioned(self):
+        with self.assertRaises(ConfigurationError) as cm:
+            self.make_app({
+                'includes': 'kinto.plugins.accounts',
+                'multiauth.policies': 'basicauth',
+            })
+        assert "Account policy missing" in str(cm.exception)
+
+
 class HelloViewTest(AccountsWebTest):
 
     def test_accounts_capability_if_enabled(self):