mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-01 19:42:12 +00:00
docs(guides): Update metadata guide (#6072)
* wip new structure * finalize * broken link
This commit is contained in:
@@ -5,158 +5,57 @@ title: User Metadata
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
In this guide you will learn how to manually create the necessary requests to authenticate and request a user's metadata from ZITADEL.
|
||||
This guide shows you how to request metadata from a user.
|
||||
ZITADEL offers multiple methods to retrieve metadata.
|
||||
Pick the one that works best for your solution.
|
||||
|
||||
Typical examples for user metadata include:
|
||||
## Use cases for metadata
|
||||
|
||||
Typical use cases for user metadata include:
|
||||
|
||||
- Link the user to an internal identifier (eg, userId, contract number, etc.)
|
||||
- Save custom user data when registering a user
|
||||
- Route upstream traffic based on user attributes
|
||||
|
||||
## Prerequisites
|
||||
## Before you start
|
||||
|
||||
### Create a new client
|
||||
Before you start you need to add some metadata to an existing user.
|
||||
You can do so by using [Console](../console/users) or [setting user metadata](/docs/apis/resources/mgmt/management-service-set-user-metadata) through the management API.
|
||||
|
||||
- Create a new [web application](../console/applications#web)
|
||||
- Use Code-Flow
|
||||
- In this example we will use `http://localhost` as redirect url
|
||||
- Make sure to note the client secret
|
||||
Most of the methods below require you to login with the correct user while setting some scopes.
|
||||
Make sure you pick the right user when logging into the test application.
|
||||
Use the [OIDC authentication request playground](/docs/apis/openidoauth/authrequest) or the configuration of an [example client](/docs/examples/introduction) to set the required scopes and receive a valid access token.
|
||||
|
||||
### Add metadata to a user
|
||||
|
||||
- [Add metadata](/guides/manage/customize/user-metadata) to a user
|
||||
- Make sure you will use this user to login during later steps
|
||||
|
||||
## Requesting a token
|
||||
|
||||
:::info
|
||||
In this guide we will manually request a token from ZITADEL for demonstration purposes. You will likely use a client library for the OpenID Authentication.
|
||||
:::info Getting a token
|
||||
In case you want to test out different settings configure an application with code flow (PKCE).
|
||||
Grab the code from the url parameter after a successful login and exchange the code for tokens by calling the [token endpoint](/docs/apis/openidoauth/endpoints#token_endpoint).
|
||||
You will find more information in our guides on how to [authenticate users](/docs/guides/integrate/login-users).
|
||||
:::
|
||||
|
||||
### Set environment variables
|
||||
## Use tokens to get user metadata
|
||||
|
||||
We will use some information throughout this guide. Set the required environment variables as follows. Make sure to replace the values with your information.
|
||||
Use one of these methods to get the metadata for the currently logged in user.
|
||||
|
||||
```bash
|
||||
export CLIENT_SECRET=QCiMffalakI...zpT0vuOsSkVk1ne \
|
||||
export CLIENT_ID="16604...@docs-claims" \
|
||||
export REDIRECT_URI="http://localhost" \
|
||||
export ZITADEL_DOMAIN="https://...asd.zitadel.cloud"
|
||||
```
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="go" label="Go" default>
|
||||
|
||||
Grab zitadel-tools to create the [required string](/apis/openidoauth/authn-methods#client-secret-basic) for Basic authentication:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:zitadel/zitadel-tools.git
|
||||
cd zitadel-tools/cmd/basicauth
|
||||
export BASIC_AUTH="$(go run basicauth.go -id $CLIENT_ID -secret $CLIENT_SECRET)"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="python" label="Python">
|
||||
|
||||
```python
|
||||
import base64
|
||||
import urllib.parse
|
||||
import os
|
||||
|
||||
clientId = os.environ.get("CLIENT_ID")
|
||||
clientSecret = os.environ.get("CLIENT_SECRET")
|
||||
|
||||
escaped = safe_string = urllib.parse.quote_plus(clientId) + ":" + urllib.parse.quote_plus(clientSecret)
|
||||
message_bytes = escaped.encode('ascii')
|
||||
base64_bytes = base64.b64encode(message_bytes)
|
||||
base64_message = base64_bytes.decode('ascii')
|
||||
|
||||
print(base64_message)
|
||||
```
|
||||
|
||||
Export the result to the environment variable `BASIC_AUTH`.
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="js" label="Javascript" default>
|
||||
|
||||
```javascript
|
||||
esc = encodeURIComponent(process.env.CLIENT_ID) + ":" + encodeURIComponent(process.env.CLIENT_SECRET)
|
||||
enc = btoa(esc)
|
||||
console.log(enc)
|
||||
```
|
||||
|
||||
Export the result to the environment variable `BASIC_AUTH`.
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="manually" label="Manually">
|
||||
|
||||
You need to create a string as described [here](/apis/openidoauth/authn-methods#client-secret-basic).
|
||||
|
||||
Use a programming language of your choice or manually create the strings with online tools (don't use these secrets for production) like:
|
||||
|
||||
- https://www.urlencoder.org/
|
||||
- https://www.base64encode.org/
|
||||
|
||||
Export the result to the environment variable `BASIC_AUTH`.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Create Auth Request
|
||||
|
||||
You need to create a valid auth request, including the reserved scope `urn:zitadel:iam:user:metadata`. Please refer to our API documentation for more information about [reserved scopes](/apis/openidoauth/scopes#reserved-scopes) or try it out in our [OIDC Authrequest Playground](/apis/openidoauth/authrequest?scope=openid%20email%20profile%20urn%3Azitadel%3Aiam%3Auser%3Ametadata).
|
||||
|
||||
Login with the user to which you have added the metadata. After the login you will be redirected.
|
||||
|
||||
Grab the code paramter from the url (disregard the &code= parameter) and export the code as environment variable:
|
||||
|
||||
```bash
|
||||
export AUTH_CODE="Y6nWsgR5WB...zUtFqSp5Xw"
|
||||
```
|
||||
|
||||
### Token Request
|
||||
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url "${ZITADEL_DOMAIN}/oauth/v2/token" \
|
||||
--header "Accept: application/json" \
|
||||
--header "Authorization: Basic ${BASIC_AUTH}" \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data grant_type=authorization_code \
|
||||
--data-urlencode "code=$AUTH_CODE" \
|
||||
--data-urlencode "redirect_uri=$REDIRECT_URI"
|
||||
```
|
||||
|
||||
The result will give you something like:
|
||||
|
||||
```json
|
||||
{
|
||||
"access_token":"jZuRixKQTVecEjKqw...kc3G4",
|
||||
"token_type":"Bearer",
|
||||
"expires_in":43199,
|
||||
"id_token":"ey...Ww"
|
||||
}
|
||||
```
|
||||
|
||||
Grab the access_token value and export as an environment variable:
|
||||
|
||||
```bash
|
||||
export ACCESS_TOKEN="jZuRixKQTVecEjKqw...kc3G4"
|
||||
```
|
||||
In case you want to manage metadata for other users than the currently logged in user, then you must use the [management service](#manage-user-metadata-through-the-management-api).
|
||||
|
||||
### Request metadata from userinfo endpoint
|
||||
|
||||
With the access token we can make a request to the userinfo endpoint to get the user's metadata. This method is the preferred method to retrieve a user's information in combination with opaque tokens, to insure that the token is valid.
|
||||
With the access token we can make a request to the [userinfo endpoint](/docs/apis/openidoauth/endpoints#introspection_endpoint) to get the user's metadata.
|
||||
This method is the preferred method to retrieve a user's information in combination with opaque tokens, to insure that the token is valid.
|
||||
|
||||
You must pass the [reserved scope](/docs/apis/openidoauth/scopes#reserved-scopes) `urn:zitadel:iam:user:metadata` in your authentication request.
|
||||
If you don't include this scope the response will contain user data, but not the metadata object.
|
||||
|
||||
Request the user information by calling the [userinfo endpoint](/docs/apis/openidoauth/endpoints#introspection_endpoint):
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url "${ZITADEL_DOMAIN}/oidc/v1/userinfo" \
|
||||
--url "https://$ZITADEL_DOMAIN/oidc/v1/userinfo" \
|
||||
--header "Authorization: Bearer $ACCESS_TOKEN"
|
||||
```
|
||||
|
||||
Replace `$ACCESS_TOKEN` with your user's access token.
|
||||
|
||||
The response will look something like this
|
||||
|
||||
```json
|
||||
@@ -178,15 +77,19 @@ The response will look something like this
|
||||
}
|
||||
```
|
||||
|
||||
You can grab the metadata from the reserved claim `"urn:zitadel:iam:user:metadata"` as key-value pairs. Note that the values are base64 encoded. So the value `MTIzNA` decodes to `1234`.
|
||||
You can grab the metadata from the reserved claim `"urn:zitadel:iam:user:metadata"` as key-value pairs.
|
||||
Note that the values are base64 encoded.
|
||||
So the value `MTIzNA` decodes to `1234`.
|
||||
|
||||
### Send metadata inside the ID token (optional)
|
||||
### Send metadata inside the ID token
|
||||
|
||||
Check "User Info inside ID Token" in the configuration of your application.
|
||||
You might want to include metadata directly into the ID Token.
|
||||
For that you need to enable "User Info inside ID Token" in your application's settings.
|
||||
|
||||

|
||||
|
||||
Now request a new token from ZITADEL.
|
||||
Now request a new token from ZITADEL by logging in with the user that has metadata attached.
|
||||
Make sure you log into the correct client/application where you enabled the settings.
|
||||
|
||||
The result will give you something like:
|
||||
|
||||
@@ -199,4 +102,129 @@ The result will give you something like:
|
||||
}
|
||||
```
|
||||
|
||||
Grab the id_token and inspect the contents of the token at [jwt.io](https://jwt.io/). You should get the same info in the ID token as when requested from the user endpoint.
|
||||
When you decode the value of `id_token`, then the response will include the metadata claim:
|
||||
|
||||
```json
|
||||
{
|
||||
"amr": [
|
||||
"password",
|
||||
"pwd",
|
||||
"mfa",
|
||||
"otp"
|
||||
],
|
||||
"at_hash": "lGIblkTr8faHz2zd0oTddA",
|
||||
"aud": [
|
||||
"170086824411201793@portal",
|
||||
"209806276543185153@portal",
|
||||
"170086774599581953"
|
||||
],
|
||||
"auth_time": 1687418556,
|
||||
"azp": "170086824411201793@portal",
|
||||
"c_hash": "dA3wre4ytCJCn11f7cIm0A",
|
||||
"client_id": "1700...1793@portal",
|
||||
"email": "road.runner@zitadel.com",
|
||||
"email_verified": true,
|
||||
"exp": 1687422272,
|
||||
"family_name": "Runner",
|
||||
"given_name": "Road",
|
||||
"iat": 1687418672,
|
||||
"iss": "https://...-abcd.zitadel.cloud",
|
||||
"locale": null,
|
||||
"name": "Road Runner",
|
||||
"preferred_username": "road.runner@...-abcd.zitadel.cloud",
|
||||
"sub": "170848145649959169",
|
||||
"updated_at": 1658329554,
|
||||
//highlight-start
|
||||
"urn:zitadel:iam:user:metadata": {
|
||||
"ContractNumber": "MTIzNA"
|
||||
}
|
||||
//highlight-end
|
||||
}
|
||||
```
|
||||
|
||||
Note that the values are base64 encoded.
|
||||
So the value `MTIzNA` decodes to `1234`.
|
||||
|
||||
:::info decoding the jwt token
|
||||
Use a website like [jwt.io](https://jwt.io/) to decode the token.
|
||||
With jq installed you can also use `jq -R 'split(".") | .[1] | @base64d | fromjson' <<< $ID_TOKEN`
|
||||
:::
|
||||
|
||||
### Request metadata from authentication API
|
||||
|
||||
You can use the authentication service to request and search for the user's metadata.
|
||||
|
||||
The introspection endpoint and the token endpoint in the examples above do not require a special scope to access.
|
||||
Yet when accessing the authentication service, you need to pass the [reserved scope](/docs/apis/openidoauth/scopes#reserved-scopes) `urn:zitadel:iam:org:project:id:zitadel:aud` along with the authentication request.
|
||||
This scope allows the user to access ZITADEL's APIs, specifically the authentication API that we need for this method.
|
||||
Use the [OIDC authentication request playground](/docs/apis/openidoauth/authrequest) or the configuration of an [example client](/docs/examples/introduction) to set the required scopes and receive a valid access token.
|
||||
|
||||
:::note Invalid audience
|
||||
If you get the error "invalid audience (APP-Zxfako)", then you need to add the reserved scope `urn:zitadel:iam:org:project:id:zitadel:aud` to your authentication request.
|
||||
:::
|
||||
|
||||
You can request the user's metadata with the [List My Metadata](/docs/apis/resources/auth/auth-service-list-my-metadata) method:
|
||||
|
||||
```bash
|
||||
curl -L -X POST "https://$ZITADEL_DOMAIN/auth/v1/users/me/metadata/_search" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json' \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
--data-raw '{
|
||||
"query": {
|
||||
"offset": "0",
|
||||
"limit": 100,
|
||||
"asc": true
|
||||
},
|
||||
"queries": [
|
||||
{
|
||||
"keyQuery": {
|
||||
"key": "$METADATA_KEY",
|
||||
"method": "TEXT_QUERY_METHOD_EQUALS"
|
||||
}
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
Replace `$ACCESS_TOKEN` with your user's access token.
|
||||
Replace `$ZITADEL_DOMAIN` with your ZITADEL instance's url.
|
||||
Replace `$METADATA_KEY` with they key you want to search for (f.e. "ContractNumber")
|
||||
|
||||
:::info Get all metadata
|
||||
You can omit the queries array to retrieve all metadata key-value pairs.
|
||||
:::
|
||||
|
||||
An example response for your search looks like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"details":{
|
||||
"totalResult":"1",
|
||||
"processedSequence":"2935",
|
||||
"viewTimestamp":"2023-06-21T16:01:52.829838Z"
|
||||
},
|
||||
"result":[
|
||||
{
|
||||
"details":{
|
||||
"sequence":"409",
|
||||
"creationDate":"2022-08-04T09:09:06.259324Z",
|
||||
"changeDate":"2022-08-04T09:09:06.259324Z",
|
||||
"resourceOwner":"170086363054473473"
|
||||
},
|
||||
"key":"ContractNumber",
|
||||
"value":"MTIzNA"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Manage user metadata through the management API
|
||||
|
||||
The previous methods allowed you to retrieve metadata only for the `sub` in the access token.
|
||||
In case you want to get the metadata for another user, you need to use the management service.
|
||||
The user that calls the management service must have [manager permissions](/docs/guides/manage/console/managers).
|
||||
A user can be either a human user or a service user.
|
||||
|
||||
You can get [metadata of a user filtered by your query](/docs/apis/resources/mgmt/management-service-list-user-metadata) or [get a metadata object from a user by a specific key](/docs/apis/resources/mgmt/management-service-get-user-metadata).
|
||||
The management service allows you to set and delete metadata, see the [API documentation for users](/docs/category/apis/resources/mgmt/users).
|
||||
|
||||
Reference in New Issue
Block a user