From 44fcd1b3d216a5fa6763b902b01683068fc47497 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Wed, 15 May 2019 14:53:27 +0100 Subject: [PATCH 1/9] Proposal for server-side password policies --- proposals/2000-password-policies.md | 76 +++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 proposals/2000-password-policies.md diff --git a/proposals/2000-password-policies.md b/proposals/2000-password-policies.md new file mode 100644 index 00000000000..207a044c777 --- /dev/null +++ b/proposals/2000-password-policies.md @@ -0,0 +1,76 @@ +# MSC 2000: Proposal for server-side password policies + +Some server administrators may want to ensure their users use passwords that +comply with a given policy. This is specifically relevant to companies and big +organisations which usually want to be able to apply a standardised password +policy across all services. + +This proposal aims to define a way for servers to enforce a configurable +password policy and for clients to be aware of it so they can provide users with +an appropriate UX. + +## Proposal + +This proposal changes the following routes: + +* `POST /_matrix/client/r0/register` +* `POST /_matrix/client/r0/account/password` + +By adding a new error response with a 400 status code: + +```json +{ + "errcode": "M_WEAK_PASSWORD", + "error": "" +} +``` + +This response would be returned by the server following a request to any of +these routes that contains a password that doesn't comply with the password +policy configured by the server's administrator. + +This proposal also adds a new route, `GET /_matrix/client/r0/password_policy`, +which would return the following response with a 200 status code: + +```json +{ + "type": "", + "params": { + // Parameters + } +} +``` + +This response format is intentionnally generic so that it allows server +administrators to rely on a custom solution, for example Dropbox's +[zxcvbn](https://github.com/dropbox/zxcvbn) tool (in which case the `params` +object could contain a `complexity` metric with a minimum complexity score the +password must reach). + +This proposal also specifies a default policy type, named `m.default_policy`, +which `params` have the form: + +```json +{ + "minimum_length": 20, + "require_digits": true, + "require_uppercase": true, + "require_lowercase": true, + "require_symbols": true +} +``` + +## Tradeoffs + +A less flexible way to define a password policy (e.g. limiting a policy's +definition to the params for `m.default_policy`) would have been simpler, +however some clients are already implementing their own passowrd complexity +policy (Riot Web, for example, uses zxcvbn), and this solution would improve the +compatibility of the proposed solution with existing software. + +Another point is that the localisation of the weak password message is here left +to the server's responsibility. This is not optimal, and there's an argument for +more detailed error codes (as opposed to a catch-all `M_WEAK_PASSWORD`). +However, this isn't really feasible with the approach described in this proposal +which allows for third-party solutions with their own criteria to evaluate a +password's complexity. From 2135dd2dd83917555f6b4a9f2c49f16d4e77ae66 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Wed, 15 May 2019 17:23:00 +0100 Subject: [PATCH 2/9] Incorporate opinions --- proposals/2000-password-policies.md | 61 +++++++++++++++++------------ 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/proposals/2000-password-policies.md b/proposals/2000-password-policies.md index 207a044c777..1d28472dc87 100644 --- a/proposals/2000-password-policies.md +++ b/proposals/2000-password-policies.md @@ -11,24 +11,6 @@ an appropriate UX. ## Proposal -This proposal changes the following routes: - -* `POST /_matrix/client/r0/register` -* `POST /_matrix/client/r0/account/password` - -By adding a new error response with a 400 status code: - -```json -{ - "errcode": "M_WEAK_PASSWORD", - "error": "" -} -``` - -This response would be returned by the server following a request to any of -these routes that contains a password that doesn't comply with the password -policy configured by the server's administrator. - This proposal also adds a new route, `GET /_matrix/client/r0/password_policy`, which would return the following response with a 200 status code: @@ -60,6 +42,42 @@ which `params` have the form: } ``` +This proposal adds new error codes to the existing list: + +* `M_PASSWORD_TOO_SHORT`: the provided password's length is shorter than the + minimum length required by the server. +* `M_PASSWORD_NO_DIGITS`: the password doesn't contain any digit but the server + requires at least one. +* `M_PASSWORD_NO_UPPERCASE`: the password doesn't contain any uppercase letter + but the server requires at least one. +* `M_PASSWORD_NO_LOWERCASE`: the password doesn't contain any lowercase letter + but the server requires at least one. +* `M_PASSWORD_NO_SYMBOLS`: the password doesn't contain any symbol but the + server requires at least one. +* `M_PASSWORD_IN_DICTIONNARY`: the password was found in a dictionnary. + +Finally, this proposal changes the following routes: + +* `POST /_matrix/client/r0/register` +* `POST /_matrix/client/r0/account/password` + +By adding new response formats with a 400 status code following this format: + +```json +{ + "errcode": "", + "error": "" +} +``` + +This response would be returned by the server following a request to any of +these routes that contains a password that doesn't comply with the password +policy configured by the server's administrator. + +In this response, `` is one of the error code described above, or +`M_WEAK_PASSWORD` if the reason the password has been refused doesn't fall into +one of these categories. + ## Tradeoffs A less flexible way to define a password policy (e.g. limiting a policy's @@ -67,10 +85,3 @@ definition to the params for `m.default_policy`) would have been simpler, however some clients are already implementing their own passowrd complexity policy (Riot Web, for example, uses zxcvbn), and this solution would improve the compatibility of the proposed solution with existing software. - -Another point is that the localisation of the weak password message is here left -to the server's responsibility. This is not optimal, and there's an argument for -more detailed error codes (as opposed to a catch-all `M_WEAK_PASSWORD`). -However, this isn't really feasible with the approach described in this proposal -which allows for third-party solutions with their own criteria to evaluate a -password's complexity. From 3adfe53e8e054af9c2f1e3ee371c923e248143ba Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Wed, 15 May 2019 17:23:47 +0100 Subject: [PATCH 3/9] Wording --- proposals/2000-password-policies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2000-password-policies.md b/proposals/2000-password-policies.md index 1d28472dc87..0bd4fe2400f 100644 --- a/proposals/2000-password-policies.md +++ b/proposals/2000-password-policies.md @@ -11,7 +11,7 @@ an appropriate UX. ## Proposal -This proposal also adds a new route, `GET /_matrix/client/r0/password_policy`, +This proposal adds a new route, `GET /_matrix/client/r0/password_policy`, which would return the following response with a 200 status code: ```json From 187b06fb3b19f34116b9705d2b8ac7020b27c8e2 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Wed, 15 May 2019 17:35:22 +0100 Subject: [PATCH 4/9] Update proposals/2000-password-policies.md Co-Authored-By: Travis Ralston --- proposals/2000-password-policies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2000-password-policies.md b/proposals/2000-password-policies.md index 0bd4fe2400f..64977e3fa7b 100644 --- a/proposals/2000-password-policies.md +++ b/proposals/2000-password-policies.md @@ -23,7 +23,7 @@ which would return the following response with a 200 status code: } ``` -This response format is intentionnally generic so that it allows server +This response format is intentionally generic so that it allows server administrators to rely on a custom solution, for example Dropbox's [zxcvbn](https://github.com/dropbox/zxcvbn) tool (in which case the `params` object could contain a `complexity` metric with a minimum complexity score the From f92f4d88ac2a14b4f76cbd171551bc11f65b6b5c Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Wed, 15 May 2019 17:36:05 +0100 Subject: [PATCH 5/9] Update proposals/2000-password-policies.md Co-Authored-By: Travis Ralston --- proposals/2000-password-policies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2000-password-policies.md b/proposals/2000-password-policies.md index 64977e3fa7b..0c295979db8 100644 --- a/proposals/2000-password-policies.md +++ b/proposals/2000-password-policies.md @@ -54,7 +54,7 @@ This proposal adds new error codes to the existing list: but the server requires at least one. * `M_PASSWORD_NO_SYMBOLS`: the password doesn't contain any symbol but the server requires at least one. -* `M_PASSWORD_IN_DICTIONNARY`: the password was found in a dictionnary. +* `M_PASSWORD_IN_DICTIONNARY`: the password was found in a dictionary, and is not acceptable. Finally, this proposal changes the following routes: From 2a0b169cf0b069f91c077aaecad0fb5ccb5238e8 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Fri, 17 May 2019 20:13:56 +0100 Subject: [PATCH 6/9] Incorporate review --- proposals/2000-password-policies.md | 70 ++++++++++++++--------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/proposals/2000-password-policies.md b/proposals/2000-password-policies.md index 0c295979db8..71dcfec152d 100644 --- a/proposals/2000-password-policies.md +++ b/proposals/2000-password-policies.md @@ -16,31 +16,29 @@ which would return the following response with a 200 status code: ```json { - "type": "", - "params": { - // Parameters + "policy": { + // Policy parameter } } ``` -This response format is intentionally generic so that it allows server -administrators to rely on a custom solution, for example Dropbox's -[zxcvbn](https://github.com/dropbox/zxcvbn) tool (in which case the `params` -object could contain a `complexity` metric with a minimum complexity score the -password must reach). +Five optional policy parameters are also specified: -This proposal also specifies a default policy type, named `m.default_policy`, -which `params` have the form: +* `m.minimum_length` (integer): Minimum accepted length for a password. +* `m.require_digits` (boolean): Wether the password must contain at least one + digit. +* `m.require_symbols` (boolean): Wether the password must contain at least one + symbol. +* `m.require_lowercase` (boolean): Wether the password must contain at least one + lowercase letter. +* `m.require_uppercase` (boolean): Wether the password must contain at least one + uppercase letter. -```json -{ - "minimum_length": 20, - "require_digits": true, - "require_uppercase": true, - "require_lowercase": true, - "require_symbols": true -} -``` +Implementations are free to add their own policy parameters in their own +namespace. This allows server administrators to rely on a custom solution, for +example Dropbox's [zxcvbn](https://github.com/dropbox/zxcvbn) tool which could +lead to a `org.example.complexity` parameter describing the minimum expected +complexity score from zxcvbn's analysis. This proposal adds new error codes to the existing list: @@ -54,29 +52,31 @@ This proposal adds new error codes to the existing list: but the server requires at least one. * `M_PASSWORD_NO_SYMBOLS`: the password doesn't contain any symbol but the server requires at least one. -* `M_PASSWORD_IN_DICTIONNARY`: the password was found in a dictionary, and is not acceptable. +* `M_PASSWORD_IN_DICTIONNARY`: the password was found in a dictionary, and is + not acceptable. Finally, this proposal changes the following routes: * `POST /_matrix/client/r0/register` * `POST /_matrix/client/r0/account/password` -By adding new response formats with a 400 status code following this format: - -```json -{ - "errcode": "", - "error": "" -} -``` - -This response would be returned by the server following a request to any of -these routes that contains a password that doesn't comply with the password -policy configured by the server's administrator. +By adding new error codes to the list of possible ones returned with a 400 +status code: -In this response, `` is one of the error code described above, or -`M_WEAK_PASSWORD` if the reason the password has been refused doesn't fall into -one of these categories. +* `M_PASSWORD_TOO_SHORT`: the provided password's length is shorter than the + minimum length required by the server. +* `M_PASSWORD_NO_DIGITS`: the password doesn't contain any digit but the server + requires at least one. +* `M_PASSWORD_NO_UPPERCASE`: the password doesn't contain any uppercase letter + but the server requires at least one. +* `M_PASSWORD_NO_LOWERCASE`: the password doesn't contain any lowercase letter + but the server requires at least one. +* `M_PASSWORD_NO_SYMBOLS`: the password doesn't contain any symbol but the + server requires at least one. +* `M_PASSWORD_IN_DICTIONNARY`: the password was found in a dictionary, and is + not acceptable. +* `M_WEAK_PASSWORD` if the reason the password has been refused doesn't fall + into one of the previous categories. ## Tradeoffs From 3d2fe12f23a7c9bc95d7740d77c115f77118db3b Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Mon, 20 May 2019 12:35:08 +0100 Subject: [PATCH 7/9] Remove redundant error codes --- proposals/2000-password-policies.md | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/proposals/2000-password-policies.md b/proposals/2000-password-policies.md index 71dcfec152d..db8c1ec05d0 100644 --- a/proposals/2000-password-policies.md +++ b/proposals/2000-password-policies.md @@ -40,21 +40,6 @@ example Dropbox's [zxcvbn](https://github.com/dropbox/zxcvbn) tool which could lead to a `org.example.complexity` parameter describing the minimum expected complexity score from zxcvbn's analysis. -This proposal adds new error codes to the existing list: - -* `M_PASSWORD_TOO_SHORT`: the provided password's length is shorter than the - minimum length required by the server. -* `M_PASSWORD_NO_DIGITS`: the password doesn't contain any digit but the server - requires at least one. -* `M_PASSWORD_NO_UPPERCASE`: the password doesn't contain any uppercase letter - but the server requires at least one. -* `M_PASSWORD_NO_LOWERCASE`: the password doesn't contain any lowercase letter - but the server requires at least one. -* `M_PASSWORD_NO_SYMBOLS`: the password doesn't contain any symbol but the - server requires at least one. -* `M_PASSWORD_IN_DICTIONNARY`: the password was found in a dictionary, and is - not acceptable. - Finally, this proposal changes the following routes: * `POST /_matrix/client/r0/register` From 34e5547ed614923a8622575f91d79a5a648a97b8 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Mon, 20 May 2019 12:37:58 +0100 Subject: [PATCH 8/9] Typo --- proposals/2000-password-policies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2000-password-policies.md b/proposals/2000-password-policies.md index db8c1ec05d0..4bf0a3791c9 100644 --- a/proposals/2000-password-policies.md +++ b/proposals/2000-password-policies.md @@ -58,7 +58,7 @@ status code: but the server requires at least one. * `M_PASSWORD_NO_SYMBOLS`: the password doesn't contain any symbol but the server requires at least one. -* `M_PASSWORD_IN_DICTIONNARY`: the password was found in a dictionary, and is +* `M_PASSWORD_IN_DICTIONARY`: the password was found in a dictionary, and is not acceptable. * `M_WEAK_PASSWORD` if the reason the password has been refused doesn't fall into one of the previous categories. From a51a057b0ac03958ffb045b852c6a5d5f9a274f8 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Mon, 20 May 2019 17:49:48 +0100 Subject: [PATCH 9/9] Don't use plural if min is 1 --- proposals/2000-password-policies.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/2000-password-policies.md b/proposals/2000-password-policies.md index 4bf0a3791c9..e4531c41f78 100644 --- a/proposals/2000-password-policies.md +++ b/proposals/2000-password-policies.md @@ -25,9 +25,9 @@ which would return the following response with a 200 status code: Five optional policy parameters are also specified: * `m.minimum_length` (integer): Minimum accepted length for a password. -* `m.require_digits` (boolean): Wether the password must contain at least one +* `m.require_digit` (boolean): Wether the password must contain at least one digit. -* `m.require_symbols` (boolean): Wether the password must contain at least one +* `m.require_symbol` (boolean): Wether the password must contain at least one symbol. * `m.require_lowercase` (boolean): Wether the password must contain at least one lowercase letter. @@ -50,13 +50,13 @@ status code: * `M_PASSWORD_TOO_SHORT`: the provided password's length is shorter than the minimum length required by the server. -* `M_PASSWORD_NO_DIGITS`: the password doesn't contain any digit but the server +* `M_PASSWORD_NO_DIGIT`: the password doesn't contain any digit but the server requires at least one. * `M_PASSWORD_NO_UPPERCASE`: the password doesn't contain any uppercase letter but the server requires at least one. * `M_PASSWORD_NO_LOWERCASE`: the password doesn't contain any lowercase letter but the server requires at least one. -* `M_PASSWORD_NO_SYMBOLS`: the password doesn't contain any symbol but the +* `M_PASSWORD_NO_SYMBOL`: the password doesn't contain any symbol but the server requires at least one. * `M_PASSWORD_IN_DICTIONARY`: the password was found in a dictionary, and is not acceptable.