9. Spar braindump

Reference: {#SparBrainDump} Author: Matthias Fischmann


this is a mix of information on inmplementation details, architecture, and operation. it should probably be sorted into different places in the future, but if you can’t find any more well-structured documentation answering your questions, look here!

9.2. operations

9.2.1. enabling / disabling the sso feature for a team

if you have sso disabled by default, you need to turn on the feature for every team that wants to use it. you can do this in the stern service (aka backoffice). look for get/put /teams/{tid}/features/sso

9.2.2. registering an idp with a team via curl

you need to have:

# user id of an admin of the team (or the creator from the team info
# in the backoffice, if you only have the team id).
export ADMIN_ID=...

# path of the xml metadata file (if you only have the url, curl it)
export METADATA_FILE=...

copy these two files to one of your spar instances:

  • .../wire-server/hack/bin/register_idp_internal.sh

  • ${METADATA_FILE}

… and ssh into it. then:

./register_idp_internal.sh metadata.xml ${TEAM_OWNER_ID}

the output contains the a json object representing the idp. construct the login code from the id field of that object by adding wire- in front, eg.:

wire-e97fbe2e-eeb1-11e9-acf3-9ba77d8a04bf

give this login code to the users that you want to connect to wire using this idp. see here on how to use the login code.

9.2.3. updating an idp via curl

Your IdP metadata may change over time (eg., because a certificate expires, or because you change vendor and all the metadata looks completely different), these changes need to be updated in wire. We offer two options to do that.

Like when creating your first IdP, for both options you need define a few things:

# user id of an admin of the team (or the creator from the team info
# in the backoffice, if you only have the team id).
export ADMIN_ID=...

# path of the xml metadata file (if you only have the url, curl it)
export METADATA_FILE=...

# The ID of the IdP you want to update (login code without the `wire-`
# prefix, which is a UUIDv4):
export IDP_ID=...

Copy the new metadata file to one of your spar instances.

Ssh into it. If you can’t, the sso docs explain how you can create a bearer token if you have the admin’s login credentials. If you follow that approach, you need to replace all mentions of -H'Z-User ...' with -H'Authorization: Bearer ...' in the following, and you won’t need $ADMIN_ID, but something like $BEARER.

There are two ways to update an IDP, described below, each with their own tradeoffs that affect users.

9.2.3.1. Option 1: Update the existing IdP in-place

Effects:

  • You keep the login code, no visible changes for your users.

  • The old IdP becomes immediately unaccessible. It will disappear from team-settings, and users will have no way of using it for authentication.

  • If the has no account on the new IdP, she won’t be able to login.

  • If a user has an account on the new IdP, but not with exactly the same user name (SAML NameID), she will not be logged in to their old account. Instead, depending on your setup, a second account is created for them, or they are blocked (both not what you want).

curl -v \
     -XPUT http://localhost:8080/identity-providers/${IDP_ID} \
     -H"Z-User: ${ADMIN_ID}" \
     -H'Content-type: application/xml' \
     -d@"${METADATA_FILE}"

9.2.3.2. Option 2: Create a second IdP, and mark it as replacing the old one.

Effects:

  • The new IdP will have a new login code. Users need to be invited to use this new login code.

  • If they use the old login code, they can keep using the old IdP as long as it is still running as before. (This option is good for smooth transitions from one IdP to the other.)

  • If they use the new login code, they will be automatically moved from the old IdP to the new one. After that, they won’t be able to use the old one any more.

  • If a user logs into the team for the first time using the old login code, no user will be created. The old IdP is marked as “replaced”, and wire only authenticates existing users with it.

  • This doesn’t currently work if you are using SCIM for provisioning, because SCIM requires you to have exactly one IdP configured in your wire team. (Internal details: https://github.com/zinfra/backend-issues/issues/1365, https://github.com/zinfra/backend-issues/issues/1377).

  • If you go to team settings, you will see the old IdP and the new one, and there is currently no way to distinguish between replaced and active IdPs. (Internal details: https://github.com/wireapp/wire-team-settings/issues/3465).

curl -v \
     -XPOST http://localhost:8080/identity-providers'?replaces='${IDP_ID} \
     -H"Z-User: ${ADMIN_ID}" \
     -H'Content-type: application/xml' \
     -d@"${METADATA_FILE}"

9.2.4. deleting an idp via curl

Read the beginning of the last section up to “Option 1”. You need ADMIN_ID (or BEARER) and IDP_ID, but not METADATA_FILE.

curl -v
     -XDELETE http://localhost:8080/identity-providers/${IDP_ID} \
     -H"Z-User: ${ADMIN_ID}" \
     -H'Content-type: application/json

If there are still users in your team with SAML credentials associated with this IdP, you will get an error. You can either move these users elsewhere, delete them manually, or purge them implicitly during deletion of the IdP:

curl -v
     -XDELETE http://localhost:8080/identity-providers/${IDP_ID}?purge=true \
     -H"Z-User: ${ADMIN_ID}" \
     -H'Content-type: application/json

Haskell code: https://github.com/wireapp/wire-server/blob/d231550f67c117b7d100c7c8c6c01b5ad13b5a7e/services/spar/src/Spar/API.hs#L217-L271

9.2.5. setting a default SSO code

To avoid having to give users the login code, a backend can also provide a default code on the endpoint /sso/settings. This needs to be set explicitly, since this is not always wanted and there might even be multiple idps (each with their own login code):

curl -XPUT ${API_URL}/i/sso/settings -H 'Content-Type: application/json' -d '{"default_sso_code":"e97fbe2e-eeb1-11e9-acf3-9ba77d8a04bf"}'

Note the lack of the wire- prefix.

This entry gets removed automatically when the corresponding idp is deleted. You can manually delete the default by making a PUT request as shown above with payload {"default_sso_code":null}.

Clients can then ask for the default SSO code on /sso/settings and use it to initiate single sign-on.

9.2.6. common misconceptions

9.2.6.1. an email address can be one of two things

When users are SAML-authenticated with an email address under NameID, that email address is used by wire as an opaque identifier, not to send actual emails. In order to also assign the user that email address, you can enable the feature flag validateSAMLemails. This will trigger the regular email validation flow that is also triggered when the user changes their email themselves.

9.2.6.2. scim, provisioning, metadata

for changing the user information (name, handle, email, …), saml isn’t enough. the identity management software (AD in this case, or some add-on) needs to support scim. we could support doing that via saml, but the part of the standards that are needed for that are even in worse shape than the ones for the authentication bits, and it would not lead to a good user experience. so instead we require users to adopt the more robust and contemporary scim standard.

9.3. application logic

9.3.1. deleting users that exist on spar

For scim- or saml-created users, there are three locations for user data:

  • brig.user (and a few things associated with that on brig and galley)

  • spar.user

  • spar.scim_user

The single source of truth is brig.user. Dangling entries in the other places are allowed, and must be checked by the application code for danglingness. (test case for scim; test case for saml)

For the semantics of interesting corner cases, consult the test suite. If you can’t find what you’re looking for there, please add at least a pending test case explaining what’s missing.

Side note: Users in brig carry an enum type ManagedBy. This is a half-implemented feature for managing conflicts between changes via scim vs. changes from wire clients; and does currently not affect deletability of users.

9.3.1.1. delete via deleting idp

Currently, we only have the rest API for this. Team settings will follow with a button.

9.3.1.2. user deletes herself

TODO

9.3.1.3. delete in team settings

TODO (probably little difference between this and “user deletes herself”?)

9.3.1.4. delete via scim

TODO