|
| 1 | +# MSC2858: Multiple SSO Identity Providers |
| 2 | + |
| 3 | +Matrix already has generic SSO support, but it does not yield the best user experience especially for |
| 4 | +instances which wish to offer multiple identity providers (IdPs). This MSC provides a simple and fully |
| 5 | +backwards compatible way to extend the current spec which would allow clients to give users options |
| 6 | +like `Continue with Google` and `Continue with Github` side-by-side. |
| 7 | + |
| 8 | +Currently, Matrix supports `m.login.sso`, `m.login.token` and `/login/sso/redirect` for clients to |
| 9 | +pass their user to the configured Identity provider and for them to come back with something which |
| 10 | +is exchangeable for a Matrix access token. This flow offers no insight to the user as to what |
| 11 | +Identity providers are available: clients can offer only a very generic `Sign in with SSO` |
| 12 | +button. With the currently possible solutions and workarounds the experience is far from great |
| 13 | +and users have to blindly click `Sign in with SSO` without any clue as to what's hiding on the other |
| 14 | +side of the door. Some users will definitely not be familiar with `SSO` but will be with the concept of |
| 15 | +"Continue with Google" or similar. |
| 16 | + |
| 17 | +## Proposal |
| 18 | + |
| 19 | +We extend the [login |
| 20 | +flow](https://matrix.org/docs/spec/client_server/r0.6.1#login) to allow clients |
| 21 | +to choose an SSO Identity provider before control is handed over to the |
| 22 | +server. The following sequence diagram illustrates the proposed, updated, login flow: |
| 23 | + |
| 24 | +<!-- source for the following is in images/2858-seq-diagram.txt --> |
| 25 | + |
| 26 | + |
| 27 | + |
| 28 | +### Extensions to login flow discovery |
| 29 | + |
| 30 | +The response to [`GET /_matrix/client/r0/login`](https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-login) |
| 31 | +is extended to **optionally** include an `identity_providers` property for |
| 32 | +flows whose type `m.login.sso`. This would look like this: |
| 33 | + |
| 34 | +```json |
| 35 | +{ |
| 36 | + "flows": [ |
| 37 | + { |
| 38 | + "type": "m.login.sso", |
| 39 | + "identity_providers": [ |
| 40 | + { |
| 41 | + "id": "google", |
| 42 | + "name": "Google", |
| 43 | + "icon": "mxc://...", |
| 44 | + "brand": "google" |
| 45 | + }, |
| 46 | + { |
| 47 | + "id": "github", |
| 48 | + "name": "Github", |
| 49 | + "icon": "mxc://...", |
| 50 | + "brand": "github" |
| 51 | + } |
| 52 | + ] |
| 53 | + }, |
| 54 | + { |
| 55 | + "type": "m.login.token" |
| 56 | + } |
| 57 | + ] |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +The value of the `identity_providers` property is a list, each entry consisting |
| 62 | +of an object with the following fields: |
| 63 | + |
| 64 | + * The `id` field is **required**. It is an opaque string chosen by the |
| 65 | + homeserver implementation, and uniquely identifies the identity provider on |
| 66 | + that server. Clients should not infer any semantic meaning from the |
| 67 | + identifier. The identifier should be between 1 and 255 characters in length, |
| 68 | + and should consist of the characters matching unreserved URI characters as |
| 69 | + defined in [RFC3986](http://www.ietf.org/rfc/rfc3986.txt): |
| 70 | + |
| 71 | + ``` |
| 72 | + ALPHA DIGIT "-" / "." / "_" / "~" |
| 73 | + ``` |
| 74 | + |
| 75 | + * The `name` field is **required**. It should be a human readable string |
| 76 | + intended for printing by the client. No explicit length limit or grammar is |
| 77 | + specified. |
| 78 | + |
| 79 | + * The `icon` field is **optional**. It should point to an icon representing |
| 80 | + the IdP. If present then it must be an MXC URI to an image resource. |
| 81 | + |
| 82 | + * The `brand` field is **optional**. It allows the client to style the login |
| 83 | + button to suit a particular brand. It should be a string using the following |
| 84 | + grammar: |
| 85 | + |
| 86 | + * Must be at least one character and no more than 255 characters in length. |
| 87 | + * Must start with one of the characters `[a-z]`, and be entirely composed |
| 88 | + of the characters `[a-z]`, `[0-9]`, `-`, `_` and `.`. |
| 89 | + |
| 90 | + To reduce confusion over which identifier should be used for each brand |
| 91 | + (for example: should "Sign in with Microsoft" be `microsoft` or |
| 92 | + `azure`?), it is proposed to maintain a registry of identifiers outside |
| 93 | + the core specification document, avoiding the need for a full MSC to add |
| 94 | + entries to the list. An initial list of proposed identifiers is given below. |
| 95 | + |
| 96 | + [Rationale: this grammar is based on the |
| 97 | + [MSC2758](https://github.com/matrix-org/matrix-doc/pull/2758), removing the |
| 98 | + requirements for a namespaced heirarchy. In |
| 99 | + [discussion](https://github.com/matrix-org/matrix-doc/pull/2858#discussion_r565506802), |
| 100 | + it was agreed that a separate registry was seen as important for a |
| 101 | + lightweight process by which implementations can agree on identifiers. The |
| 102 | + registry makes the namespacing of MSC2758 redundant; the namespacing system |
| 103 | + was also somewhat confusing.] |
| 104 | + |
| 105 | + Server implementations are free to add additional brands, though they should |
| 106 | + be mindful of clients which do not recognise any given brand. |
| 107 | + |
| 108 | + Clients are free to implement any set of brands they wish, including all or |
| 109 | + any of the brands listed in the registry, but are expected to apply a |
| 110 | + sensible unbranded fallback for any brand they do not recognise/support. |
| 111 | + |
| 112 | + Where `icon` and `brand` are both present, it is recommended that clients |
| 113 | + which support the `brand` give precedence to `brand` over `icon`. |
| 114 | + |
| 115 | +### Extend the `/login/sso/redirect` endpoint |
| 116 | + |
| 117 | +A new endpoint is added to support redirecting directly to one of the IdPs: |
| 118 | + |
| 119 | +`GET /_matrix/client/r0/login/sso/redirect/{idp_id}` |
| 120 | + |
| 121 | +This would behave identically to the existing endpoint without the last argument |
| 122 | +except would allow the server to forward the user directly to the correct IdP. |
| 123 | + |
| 124 | +For the case of backwards compatibility the existing endpoint is to remain, |
| 125 | +and if the server supports multiple SSO IdPs it should offer the user a page |
| 126 | +which lets them choose between the available IdP options as a fallback. |
| 127 | + |
| 128 | +If the `idp_id` is unrecognised, the server should display some sort of error |
| 129 | +page to the user. (A protocol whereby an error can be returned to the original |
| 130 | +client could be a matter for a future improvement, but is out of scope for now.) |
| 131 | + |
| 132 | +### Notes on user-interactive auth |
| 133 | + |
| 134 | +No change is proposed to the SSO flow for User-Interactive Authentication. |
| 135 | + |
| 136 | +For a reauthentication operation, the server implementation is free to choose |
| 137 | +any suitable IdP to authenticate the user. (Often, this will simply be |
| 138 | +the IdP that the user logged in with.) |
| 139 | + |
| 140 | +### Proposed initial identifiers for the `brand` indentifier |
| 141 | + |
| 142 | +The following identifiers are proposed for the initial content of the `brand` |
| 143 | +identifier registry. The descriptions are guidelines to help server |
| 144 | +administrators pick a suitable brand identifier, and to help client authors |
| 145 | +style buttons in their clients. |
| 146 | + |
| 147 | + * Identifier: `apple` |
| 148 | + |
| 149 | + Description: Suitable for "Sign in with Apple": see |
| 150 | + https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/. |
| 151 | + |
| 152 | + * Identifier: `facebook` |
| 153 | + |
| 154 | + Description: "Continue with Facebook": see |
| 155 | + https://developers.facebook.com/docs/facebook-login/web/login-button/. |
| 156 | + |
| 157 | + * Identifier: `github` |
| 158 | + |
| 159 | + Description: Logos available at https://github.com/logos. |
| 160 | + |
| 161 | + * Identifier: `gitlab` |
| 162 | + |
| 163 | + Description: Logos available at https://about.gitlab.com/press/press-kit/. |
| 164 | + |
| 165 | + * Identifier: `google` |
| 166 | + |
| 167 | + Description: Suitable for "Google Sign-In": see |
| 168 | + https://developers.google.com/identity/branding-guidelines. |
| 169 | + |
| 170 | + * Identifier: `twitter` |
| 171 | + |
| 172 | + Description: Suitable for "Log in with Twitter": see |
| 173 | + https://developer.twitter.com/en/docs/authentication/guides/log-in-with-twitter#tab1. |
| 174 | + |
| 175 | +When considering a new identifier for private use, administrators should pick |
| 176 | +some sensible name following the advice of [RFC6648 sec |
| 177 | +3](https://tools.ietf.org/html/rfc6648#section-3). |
| 178 | + |
| 179 | +## Alternatives |
| 180 | + |
| 181 | +An alternative to the whole approach would be to allow `m.login.sso.$idp` but this forces |
| 182 | +treating an opaque identifier as hierarchical and offers worse backwards compatibility. |
| 183 | + |
| 184 | +An alternative to the proposed backwards compatibility plan where the server offers a |
| 185 | +fallback page which fills the gap and lets the user choose which SSO IdP they need is |
| 186 | +for the server to deterministically always pick one, maybe the first option and let |
| 187 | +old clients only auth via that one but that means potentially locking users out of their |
| 188 | +accounts. |
| 189 | + |
| 190 | +[MSC2964](https://github.com/matrix-org/matrix-doc/pull/2964) proposes |
| 191 | +replacing much of Matrix's authentication mechanism with OAuth2.0. If that is |
| 192 | +adopted, then the Matrix client would not be able to specify an authentication |
| 193 | +mechanism; rather it is left up to the server to host pages allowing the user |
| 194 | +to choose their authentication mechanism. |
| 195 | + |
| 196 | +### Styling information as an alternative to `brand` |
| 197 | + |
| 198 | +The `brand` field is intended to allow clients to style "login" buttons according |
| 199 | +to the identity provider in question. For example, a mobile application might |
| 200 | +show: |
| 201 | + |
| 202 | + |
| 203 | + |
| 204 | +Some identity providers have very specific rules about how such buttons should |
| 205 | +be presented, so a fine level of control is important. |
| 206 | + |
| 207 | +An alternative way to achieve this would be for the server to give full details |
| 208 | +about the styling: icon, font colour, border colour, background colour, |
| 209 | +etc. However, this soon becomes unscalable. For example, it might be desirable |
| 210 | +to offer each logo at a range of resolutions to suit different screen sizes. |
| 211 | +Likewise, some brands need different styling depending on the background |
| 212 | +colour, so a complete second set of colours must be specified to account for |
| 213 | +dark or light themes. |
| 214 | + |
| 215 | +## Potential issues |
| 216 | + |
| 217 | + * New Identity Providers added by server administators will be unbranded until |
| 218 | + clients adopt support for the new brand. |
| 219 | + |
| 220 | +## Security considerations |
| 221 | + |
| 222 | +This could potentially aid phishing attacks by bad homeservers, where if the app says |
| 223 | +`Continue with Google` and then they are taken to a page which is styled to look like |
| 224 | +the Google login page they might be a tiny bit more susceptible to being phished as opposed |
| 225 | +as to when they click a more generic `Sign in with SSO` button, but this attack was possible |
| 226 | +anyhow using a different vector of a controlled Element/client instance which modifies |
| 227 | +the text. |
| 228 | + |
| 229 | + |
| 230 | +## Unstable prefix |
| 231 | + |
| 232 | +Whilst in development use `org.matrix.msc2858.identity_providers` for the flow |
| 233 | +discovery and |
| 234 | +`/_matrix/client/unstable/org.matrix.msc2858/login/sso/redirect/{idp_id}` for |
| 235 | +the new endpoints. |
| 236 | + |
| 237 | +When identity providers are listed under the experimental |
| 238 | +`org.matrix.msc2858.identity_providers` field of the response to `/login`, |
| 239 | +(instead of `identity_providers`), different values for the `brand` field are |
| 240 | +used. In particular the following were defined: |
| 241 | + |
| 242 | + * `org.matrix.gitlab` (now `gitlab`). |
| 243 | + * `org.matrix.github` (now `github`). |
| 244 | + * `org.matrix.apple` (now `apple`). |
| 245 | + * `org.matrix.google` (now `google`). |
| 246 | + * `org.matrix.facebook` (now `facebook`). |
| 247 | + * `org.matrix.twitter` (now `twitter`). |
0 commit comments