-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SCIM provisioning API basic implementation #17144
Open
azmeuk
wants to merge
55
commits into
element-hq:develop
Choose a base branch
from
yaal-coop:msc4098-scim
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
55 commits
Select commit
Hold shift + click to select a range
f0aa456
feat: SCIM implementation
azmeuk 28fc1a2
fix: scim typing lint errors
azmeuk c6dbad3
update to scim-models 0.1.15 and fix a bunch of mypy errors
azmeuk 634a22d
Merge branch 'develop' into msc4098-scim
azmeuk 04c39c0
update to scim-models 0.2.0
azmeuk c2fb23a
Merge branch 'develop' into msc4098-scim
azmeuk 5fafaf8
Merge branch 'develop' into msc4098-scim
azmeuk 8c0d548
Merge branch 'develop' into msc4098-scim
azmeuk f1c1afd
Merge branch 'develop' into msc4098-scim
azmeuk 8904913
fix poetry.lock
azmeuk 0fe2423
avoid raising ImportError if scim2_models is absent
azmeuk 965a341
avoid raising ImportError if scim2_models is absent
azmeuk 7c6f673
use forwardrefs to avoid using possibly unimported types
azmeuk 6f23459
skip scim2 tests if scim2-models is not installed
azmeuk a548e44
Merge branch 'develop' into msc4098-scim
azmeuk 76afb5d
Merge branch 'develop' into msc4098-scim
azmeuk 06cd88f
use SCIM_PREFIX in homeserver.py
azmeuk 35da83c
Merge branch 'develop' into msc4098-scim
azmeuk 4311e65
make SCIM_PREFIX resource not the last from homeserver
azmeuk 38bfddc
Update synapse/rest/scim.py
azmeuk 63cd06c
Merge branch 'develop' into msc4098-scim
azmeuk f2619f3
fix: regenerated poetry.lock from the develop branch
azmeuk 86fa3d1
feat: hide the SCIM API endpoint behind the msc4098 experimental feature
azmeuk c6199a3
doc: indications about SCIM being an experimental feature
azmeuk bd25a92
refactor: move the SCIM path from /_matrix/client/unstable/coop.yaal/…
azmeuk 6e36431
doc: fix an internal documentation link
azmeuk afbd62d
fix: start and count attributes cannot be negative
azmeuk 344b11e
doc: new attempt to fix the internal link to user_admin_api.md
azmeuk 5f24645
tests: asserts that users are deactivated after a call to the DELETE …
azmeuk d8ebb1c
refactor: rename 'default_display_name' var into 'display_name'
azmeuk d042676
doc: add docstrings to the SCIM endpoints
azmeuk 4c0b639
fix: Disable SCIM if Pydantic version is under 2.7
azmeuk 55107bb
fix: parse the request with scim2-models for POST and PUT endpoints
azmeuk 5774d32
refactor: remove an useless call to _create_registration_details
azmeuk 6a163ce
fix: remove falsy mention to HTTP Basic auth
azmeuk 3ebdad7
chore: bump to scim2-models 0.2.5
azmeuk feb5eba
fix: remove scim from the 'all' extra
azmeuk 0ed5962
fix: linting
azmeuk a5a2717
fix: add the 'scim' extra to the mypy GHA step
azmeuk 05f773f
refactor: move set_avatar_url from SsoHandler to ProfileHandler
azmeuk 0e0abef
refactor: extract mxc_to_http to make usable outside of jinja contexts
azmeuk aeaf74d
fix: SCIM API actually downloads the avatar pictures and store them
azmeuk 462ad10
Merge branch 'develop' into msc4098-scim
azmeuk 48306b0
fix: the page count is maxed to 1000
azmeuk 0f264ec
fix: properly store external_ids in a special __scim__ auth provider
azmeuk c48e731
fix: lint
azmeuk 36a600c
feat: make the SCIM IPD id configurable
azmeuk afc8dd7
doc: update the documentation configuration sample to match the new f…
azmeuk 3e52de5
fix: SCIM API servlet registration
azmeuk e69fd95
fix: do not return empty lists in user payloads
azmeuk e2e1bd0
fix: use the application/scim+json content-header in the SCIM API
azmeuk cb10268
Merge branch 'develop' into msc4098-scim
azmeuk 3027a7d
Merge branch 'develop' into msc4098-scim
azmeuk 668a8b8
Revert "fix: Disable SCIM if Pydantic version is under 2.7"
azmeuk f425121
chore: restore an empty line in pyproject.toml
azmeuk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Implement a SCIM provisioning API. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,284 @@ | ||
# SCIM API | ||
|
||
Synapse implements a basic subset of the SCIM 2.0 provisioning protocol as defined in [RFC7643](https://datatracker.ietf.org/doc/html/rfc7643) and [RFC7644](https://datatracker.ietf.org/doc/html/rfc7643). | ||
This allows Identity Provider software to update user attributes in a standard and centralized way. | ||
|
||
The SCIM endpoint is `/_synapse/admin/scim/v2`. | ||
|
||
<div class="warning"> | ||
|
||
The synapse SCIM API is an experimental feature, and it is disabled by default. | ||
It might be removed someday in favor of an implementation in the [Matrix Authentication Service](https://github.com/element-hq/matrix-authentication-service). | ||
|
||
</div> | ||
|
||
## Installation | ||
|
||
SCIM support for Synapse requires python 3.9+. The `matrix-synapse` package should be installed with the `scim` extra. e.g. with `pip install matrix-synapse[scim]`. For compatibility reasons, the SCIM support cannot be included in the `all` extra, so you need to explicitly use the `scim` extra to enable the API. | ||
|
||
Then it must be explicitly enabled by configuration: | ||
|
||
```yaml | ||
experimental_features: | ||
msc4098: | ||
enabled: true | ||
idp_id: <my-provider> | ||
``` | ||
|
||
## Examples | ||
|
||
This sections presents examples of SCIM requests and responses that are supported by the synapse implementation. | ||
Tools like [scim2-cli](https://scim2-cli.readthedocs.io) can be used to manually build payloads and send requests to the SCIM endpoint. | ||
|
||
### Create user | ||
|
||
#### Request | ||
|
||
``` | ||
POST /_synapse/admin/scim/v2/Users | ||
``` | ||
|
||
```json | ||
{ | ||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], | ||
"userName": "bjensen", | ||
"externalId": "bjensen@test", | ||
"phoneNumbers": [{"value": "+1-12345678"}], | ||
"emails": [{"value": "[email protected]"}], | ||
"photos": [ | ||
{ | ||
"type": "photo", | ||
"primary": true, | ||
"value": "https://mydomain.tld/photo.webp" | ||
} | ||
], | ||
"displayName": "bjensen display name", | ||
"password": "correct horse battery staple" | ||
} | ||
``` | ||
|
||
#### Response | ||
|
||
```json | ||
{ | ||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], | ||
"meta": { | ||
"resourceType": "User", | ||
"created": "2024-07-22T16:59:16.326188+00:00", | ||
"lastModified": "2024-07-22T16:59:16.326188+00:00", | ||
"location": "https://synapse.example/_synapse/admin/scim/v2/Users/@bjensen:test", | ||
}, | ||
"id": "@bjensen:test", | ||
"externalId": "@bjensen:test", | ||
"phoneNumbers": [{"value": "+1-12345678"}], | ||
"userName": "bjensen", | ||
"emails": [{"value": "[email protected]"}], | ||
"active": true, | ||
"photos": [ | ||
{ | ||
"type": "photo", | ||
"primary": true, | ||
"value": "https://mydomain.tld/photo.webp" | ||
} | ||
], | ||
"displayName": "bjensen display name" | ||
} | ||
``` | ||
|
||
### Get user | ||
|
||
#### Request | ||
|
||
``` | ||
GET /_synapse/admin/scim/v2/Users/@bjensen:test | ||
``` | ||
|
||
#### Response | ||
|
||
```json | ||
{ | ||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], | ||
"meta": { | ||
"resourceType": "User", | ||
"created": "2024-07-22T16:59:16.326188+00:00", | ||
"lastModified": "2024-07-22T16:59:16.326188+00:00", | ||
"location": "https://synapse.example/_synapse/admin/scim/v2/Users/@bjensen:test", | ||
}, | ||
"id": "@bjensen:test", | ||
"externalId": "@bjensen:test", | ||
"phoneNumbers": [{"value": "+1-12345678"}], | ||
"userName": "bjensen", | ||
"emails": [{"value": "[email protected]"}], | ||
"active": true, | ||
"photos": [ | ||
{ | ||
"type": "photo", | ||
"primary": true, | ||
"value": "https://mydomain.tld/photo.webp" | ||
} | ||
], | ||
"displayName": "bjensen display name" | ||
} | ||
``` | ||
|
||
### Get users | ||
|
||
#### Request | ||
|
||
Note that requests can be paginated using the `startIndex` and the `count` query string parameters: | ||
|
||
``` | ||
GET /_synapse/admin/scim/v2/Users?startIndex=10&count=1 | ||
``` | ||
|
||
<div class="warning"> | ||
|
||
For performances reason, the page count will be maxed to 1000. | ||
|
||
</div> | ||
|
||
#### Response | ||
|
||
```json | ||
{ | ||
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"], | ||
"totalResults": 123, | ||
"Resources": [ | ||
{ | ||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], | ||
"meta": { | ||
"resourceType": "User", | ||
"created": "2024-07-22T16:59:16.326188+00:00", | ||
"lastModified": "2024-07-22T16:59:16.326188+00:00", | ||
"location": "https://synapse.example/_synapse/admin/scim/v2/Users/@bjensen:test", | ||
}, | ||
"id": "@bjensen:test", | ||
"externalId": "@bjensen:test", | ||
"phoneNumbers": [{"value": "+1-12345678"}], | ||
"userName": "bjensen", | ||
"emails": [{"value": "[email protected]"}], | ||
"active": true, | ||
"photos": [ | ||
{ | ||
"type": "photo", | ||
"primary": true, | ||
"value": "https://mydomain.tld/photo.webp" | ||
} | ||
], | ||
"displayName": "bjensen display name" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
### Replace user | ||
|
||
#### Request | ||
|
||
``` | ||
PUT /_synapse/admin/scim/v2/Users/@bjensen:test | ||
``` | ||
|
||
```json | ||
{ | ||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], | ||
"userName": "bjensen", | ||
"externalId": "bjensen@test", | ||
"phoneNumbers": [{"value": "+1-12345678"}], | ||
"emails": [{"value": "[email protected]"}], | ||
"active": true, | ||
"photos": [ | ||
{ | ||
"type": "photo", | ||
"primary": true, | ||
"value": "https://mydomain.tld/photo.webp" | ||
} | ||
], | ||
"displayName": "bjensen new display name", | ||
"password": "correct horse battery staple" | ||
} | ||
``` | ||
|
||
#### Response | ||
|
||
```json | ||
{ | ||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], | ||
"meta": { | ||
"resourceType": "User", | ||
"created": "2024-07-22T16:59:16.326188+00:00", | ||
"lastModified": "2024-07-22T17:34:12.834684+00:00", | ||
"location": "https://synapse.example/_synapse/admin/scim/v2/Users/@bjensen:test", | ||
}, | ||
"id": "@bjensen:test", | ||
"externalId": "@bjensen:test", | ||
"phoneNumbers": [{"value": "+1-12345678"}], | ||
"userName": "bjensen", | ||
"emails": [{"value": "[email protected]"}], | ||
"active": true, | ||
"photos": [ | ||
{ | ||
"type": "photo", | ||
"primary": true, | ||
"value": "https://mydomain.tld/photo.webp" | ||
} | ||
], | ||
"displayName": "bjensen new display name" | ||
} | ||
``` | ||
|
||
### Delete user | ||
|
||
User deletion requests [deactivate](../../../admin_api/user_admin_api.md) users, with the `erase` option. | ||
|
||
#### Request | ||
|
||
``` | ||
DELETE /_synapse/admin/scim/v2/Users/@bjensen:test | ||
``` | ||
|
||
azmeuk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
## Implementation details | ||
|
||
### Models | ||
|
||
The only SCIM resource type implemented is `User`, with the following attributes: | ||
- `userName` | ||
- `password` | ||
- `emails` | ||
- `phoneNumbers` | ||
- `displayName` | ||
- `photos` (as a MXC URI) | ||
- `active` | ||
|
||
The other SCIM User attributes will be ignored. Other resource types such as `Group` are not implemented. | ||
|
||
### Endpoints | ||
|
||
The implemented endpoints are: | ||
|
||
- `/Users` (GET, POST) | ||
- `/Users/<user_id>` (GET, PUT, DELETE) | ||
- `/ServiceProviderConfig` (GET) | ||
- `/Schemas` (GET) | ||
- `/Schemas/<schema_id>` (GET) | ||
- `/ResourceTypes` (GET) | ||
- `/ResourceTypes/<resource_type_id>` | ||
|
||
The following endpoints are not implemented: | ||
|
||
- `/Users` (PATCH) | ||
- [`/Me`](https://datatracker.ietf.org/doc/html/rfc7644#section-3.11) (GET, POST, PUT, PATCH, DELETE) | ||
- `/Groups` (GET, POST, PUT, PATCH) | ||
- [`/Bulk`](https://datatracker.ietf.org/doc/html/rfc7644#section-3.7) (POST) | ||
- [`/.search`](https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.3) (POST) | ||
|
||
### Features | ||
|
||
The following features are implemented: | ||
- [pagination](https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.2.4) | ||
|
||
The following features are not implemented: | ||
- [filtering](https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.2.2) | ||
- [sorting](https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.2.3) | ||
- [attributes selection](https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.2.5) | ||
- [ETags](https://datatracker.ietf.org/doc/html/rfc7644#section-3.14) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given this functionality is in an unstable MSC, please can you:
experimental_features
flag to the configuration for this feature. SCIM should only be enabled if it is turned onmsc3861_oauth_delegation_enabled
), since in that scenario Synapse is not its own authority in charge of users?
We don't normally document experimental features however I am glad for the documentation this time. So, I'm happy to keep it, but it needs to be obvious to readers that it's experimental and not enabled by default.