feat: implement user schema management (#7416)

This PR adds the functionality to manage user schemas through the new user schema service.
It includes the possibility to create a basic JSON schema and also provides a way on defining permissions (read, write) for owner and self context with an annotation.

Further annotations for OIDC claims and SAML attribute mappings will follow.

A guide on how to create a schema and assign permissions has been started. It will be extended though out the process of implementing the schema and users based on those.

Note:
This feature is in an early stage and therefore not enabled by default. To test it out, please enable the UserSchema feature flag on your instance / system though the feature service.
This commit is contained in:
Livio Spring
2024-03-12 14:50:13 +01:00
committed by GitHub
parent 2a39cc16f5
commit 0e181b218c
61 changed files with 3614 additions and 35 deletions

View File

@@ -0,0 +1,135 @@
---
title: User Schema
---
ZITADEL allows you to define schemas for users, based on the [JSON Schema Standard](https://json-schema.org/).
This gives you the possibility to define your own data models for your users, validate them based on these definitions
and making sure who has access or manipulate information of the user.
By defining multiple schemas, you can even differentiate between different personas of your organization or application
and restrictions, resp. requirements for them to authenticate.
For example, you could have separate schemas for your employees and your customers. While you might want to make sure that
certain data like given name and family name are required for employees, they might be optional for the latter.
Or you might want to disable username password authentication for your admins and only allow phishing resistant methods like passkeys,
but still allow it for your customers.
:::info
Please be aware that User Schema is in a [preview stage](/support/software-release-cycles-support#preview) not feature complete
and therefore not generally available.
Do not use it for production yet. To test it out, you need to enable the `UserSchema` [feature flag](/apis/resources/feature_service_v2/feature-service).
:::
## Create your first schema
Let's create the first very simple schema `user`, which defines a `givenName` and `familyName` for a user and allows them to
authenticate with username and password.
We can do so by calling the [create user schema endpoint](/docs/apis/resources/user_schema_service_v3/user-schema-service-create-user-schema)
with the following data. Make sure to provide an access_token with an IAM_OWNER role.
```bash
curl -X POST "https://$CUSTOM-DOMAIN/v3alpha/user_schemas" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
--data-raw '{
"type": "user",
"schema": {
"$schema": "urn:zitadel:schema:v1",
"type": "object",
"properties": {
"givenName": {
"type": "string"
},
"familyName": {
"type": "string"
}
}
},
"possibleAuthenticators": [
"AUTHENTICATOR_TYPE_USERNAME",
"AUTHENTICATOR_TYPE_PASSWORD"
]
}'
```
This will return something similar to:
```json
{
"id": "257199613398745508",
"details": {
"sequence": "2",
"change_date": "2024-03-07T08:08:35.963956Z",
"resource_owner": "253750309325636004"
}
}
```
So you successfully create a schema and could use that to manage your users based on that.
But let's first checkout some possibilities ZITADEL offers.
## Assign Permissions
In the first step we've created a very simple `user` schema with only `givenName` and `familyName`.
This allows any user with the permission to edit the user's data to change these values.
Let's now update the schema and add some more properties and restrict who's able to retrieve and change data.
By setting `urn:zitadel:schema:permission` to fields, we can define the permissions for that field of different user roles / context.
For example by adding it to the `givenName` and `familyName` we can keep the state from before, where any `owner` (e.g. ORG_OWNER)
as well as the user themselves (`self`) are allowed to read (`r`) and write (`w`) the data.
Let's now assume our service provides some profile information of the user on a dedicated page.
Since we do not want the user to be able to change that value, we set the permission of `self` to `r`, meaning they will be able
to see the `profileUri` value, but cannot update it.
Maybe we also have some `customerId`, which the user should not even know about. We therefore can simply omit the `self` permission
and only set `owner` to `rw`, so admins are able to read and change the id if needed.
Finally, we call the [update user schema endpoint](/docs/apis/resources/user_schema_service_v3/user-schema-service-update-user-schema)
with the following data. Be sure to provide the id of the previously created schema.
```bash
curl -X PUT "https://$CUSTOM-DOMAIN/v3alpha/user_schemas/$SCHEMA_ID" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
--data-raw '{
"schema": {
"$schema": "urn:zitadel:schema:v1",
"type": "object",
"properties": {
"givenName": {
"type": "string",
"urn:zitadel:schema:permission": {
"owner": "rw",
"self": "rw"
}
},
"familyName": {
"type": "string",
"urn:zitadel:schema:permission": {
"owner": "rw",
"self": "rw"
}
},
"profileUri": {
"type": "string",
"format": "uri",
"urn:zitadel:schema:permission": {
"owner": "rw",
"self": "r"
}
},
"customerId": {
"type": "string",
"urn:zitadel:schema:permission": {
"owner": "rw"
}
}
}
}
}
```

View File

@@ -165,6 +165,7 @@ module.exports = {
items: [
"guides/manage/user/reg-create-user",
"guides/manage/customize/user-metadata",
"guides/manage/customize/user-schema",
],
},
],