Skip to content

Commit

Permalink
Update spar docs (#3038)
Browse files Browse the repository at this point in the history
Co-authored-by: Leif Battermann <[email protected]>
  • Loading branch information
fisx and battermann authored Feb 3, 2023
1 parent f6e46c3 commit 8051138
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 206 deletions.
1 change: 1 addition & 0 deletions changelog.d/4-docs/pr-3038
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Update SAML/SCIM docs
125 changes: 0 additions & 125 deletions docs/src/developer/reference/spar-braindump.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,6 @@ documentation answering your questions, look here!
- if you want to work on our saml/scim implementation and do not have access to [https://github.com/zinfra/backend-issues/issues?q=is%3Aissue+is%3Aopen+label%3Aspar] and [https://github.com/wireapp/design-specs/tree/master/Single%20Sign%20On], please get in touch with us.


## design considerations

### SCIM without SAML.

Before https://github.com/wireapp/wire-server/pull/1200, scim tokens could only be added to teams that already had exactly one SAML IdP. Now, we also allow SAML-less teams to have SCIM provisioning. This is an alternative to onboarding via team-settings and produces user accounts that are authenticated with email and password. (Phone may or may not work, but is not officially supported.)

The way this works is different from team-settings: we don't send invites, but we create active users immediately the moment the SCIM user post is processed. The new thing is that the created user has neither email nor phone nor a SAML identity, nor a password.

How does this work?

**email:** If no SAML IdP is present, SCIM user posts must contain an externalId that is an email address. This email address is not added to the newly created user, because it has not been validated. Instead, the flow for changing an email address is triggered in brig: an email is sent to the address containing a validation key, and once the user completes the flow, brig will add the email address to the user. We had to add very little code for this in this PR, it's all an old feature.

When SCIM user gets are processed, in order to reconstruct the externalId from the user spar is retrieving from brig, we introduce a new json object for the `sso_id` field that looks like this: `{'scim_external_id': '[email protected]'}`.

In order to find users that have email addresses pending validation, we introduce a new table in spar's cassandra called `scim_external_ids`, in analogy to `user`. We have tried to use brig's internal `GET /i/user&email=...`, but that also finds pending email addresses, and there are corner cases when changing email addresses and waiting for the new address to be validated and the old to be removed... that made this approach seem infeasible.

**password:** once the user has validated their email address, they need to trigger the "forgot password" flow -- also old code.


## operations

### enabling / disabling the sso feature for a team
Expand Down Expand Up @@ -226,35 +207,6 @@ This entry gets removed automatically when the corresponding idp is deleted. You
Clients can then ask for the default SSO code on `/sso/settings` and use it to initiate single sign-on.


### troubleshooting

#### gathering information

- find metadata for team in table `spar.idp_raw_metadata` via cqlsh
(since https://github.com/wireapp/wire-server/pull/872)

- ask user for screenshots of the error message, or even better, for
the text. the error message contains lots of strings that you can
grep for in the spar sources.


#### making spar work with a new IdP

often, new IdPs work out of the box, because there appears to be some
consensus about what minimum feature set everybody should support.

if there are problems: collect the metadata xml and an authentication
response xml (either from the browser http logs via a more technically
savvy customer; FUTUREWORK: it would be nice to log all saml response
xml files that spar receives in prod and cannot process).

https://github.com/wireapp/saml2-web-sso supports writing [unit vendor
compatibility
tests](https://github.com/wireapp/saml2-web-sso/blob/ff9b9f445475809d1fa31ef7f2932caa0ed31613/test/Test/SAML2/WebSSO/APISpec.hs#L266-L329)
against that response value. once that test passes, it should all
work fine.


### common misconceptions


Expand Down Expand Up @@ -325,80 +277,3 @@ TODO (probably little difference between this and "user deletes herself"?)
#### delete via scim

TODO


## using the same IdP (same entityID, or Issuer) with different teams

Some SAML IdP vendors do not allow to set up fresh entityIDs (issuers)
for fresh apps; instead, all apps controlled by the IdP are receiving
SAML credentials from the same issuer.

In the past, wire has used the a tuple of IdP issuer and 'NameID'
(Haskell type 'UserRef') to uniquely identity users (tables
`spar.user_v2` and `spar.issuer_idp`).

In order to allow one IdP to serve more than one team, this has been
changed: we now allow to identity an IdP by a combination of
entityID/issuer and wire `TeamId`. The necessary tweaks to the
protocol are listed here.

For everybody using IdPs that do not have this limitation, we have
taken great care to not change the behavior.


### what you need to know when operating a team or an instance

No instance-level configuration is required.

If your IdP supports different entityID / issuer for different apps,
you don't need to change anything. We hope to deprecate the old
flavor of the SAML protocol eventually, but we will keep you posted in
the release notes, and give you time to react.

If your IdP does not support different entityID / issuer for different
apps, keep reading. At the time of writing this section, there is no
support for multi-team IdP issuers in team-settings, so you have two
options: (1) use the rest API directly; or (2) contact our customer
support and send them the link to this section.

If you feel up to calling the rest API, try the following:

- Use the above end-point `GET /sso/metadata/:tid` with your `TeamId`
for pulling the SP metadata.
- When calling `POST /identity-provider`, make sure to add
`?api_version=v2`. (`?api_version=v1` or no omission of the query
param both invoke the old behavior.)

NB: Neither version of the API allows you to provision a user with the
same Issuer and same NamdID. RATIONALE: this allows us to implement
'getSAMLUser' without adding 'TeamId' to 'UserRef', which in turn
would break the (admittedly leaky) abstarctions of saml2-web-sso.


### API changes in more detail

- New query param `api_version=<v1|v2>` for `POST
/identity-providers`. The version is stored in `spar.idp` together
with the rest of the IdP setup, and is used by `GET
/sso/initiate-login` (see below).
- `GET /sso/initiate-login` sends audience based on api_version stored
in `spar.idp`: for v1, the audience is `/sso/finalize-login`; for
v2, it's `/sso/finalize-login/:tid`.
- New end-point `POST /sso/finalize-login/:tid` that behaves
indistinguishable from `POST /sso/finalize-login`, except when more
than one IdP with the same issuer, but different teams are
registered. In that case, this end-point can process the
credentials by discriminating on the `TeamId`.
- `POST /sso/finalize-login/:tid` remains unchanged.
- New end-point `GET /sso/metadata/:tid` returns the same SP metadata as
`GET /sso/metadata`, with the exception that it lists
`"/sso/finalize-login/:tid"` as the path of the
`AssertionConsumerService` (rather than `"/sso/finalize-login"` as
before).
- `GET /sso/metadata` remains unchanged, and still returns the old SP
metadata, without the `TeamId` in the paths.


### database schema changes

[V15](https://github.com/wireapp/wire-server/blob/b97439756cfe0721164934db1f80658b60de1e5e/services/spar/schema/src/V15.hs#L29-L43)
5 changes: 3 additions & 2 deletions docs/src/understand/single-sign-on/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
:glob: true
:maxdepth: 1
Single sign-on and user provisioning <understand/main>
Single sign-on and user provisioning: the user manual <understand/main>
Trouble shooting and FAQ <trouble-shooting.md>
Generic setup <generic-setup>
SSO integration with ADFS <adfs/main>
SSO integration with Azure <azure/main>
SSO integration with Centrify <centrify/main>
SSO integration with Okta <okta/main>
*
Internals for the intensely curious </developer/reference/spar-braindump>
```
Loading

0 comments on commit 8051138

Please sign in to comment.