Skip to main content

User Metadata

In this guide you will learn how to manually create the necessary requests to authenticate and request a user's metadata from ZITADEL.

Typical examples 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

Create a new client

  • Create a new web application
  • Use Code-Flow
  • In this example we will use http://localhost as redirect url
  • Make sure to note the client secret

Add metadata to a user

  • Add 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.

Set environment variables

We will use some information throughout this guide. Set the required environment variables as follows. Make sure to replace the values with your information.

export CLIENT_SECRET=QCiMffalakI...zpT0vuOsSkVk1ne \
export CLIENT_ID="16604...@docs-claims" \
export REDIRECT_URI="http://localhost" \
export ZITADEL_DOMAIN="https://...asd.zitadel.cloud"

Grab zitadel-tools to create the required string for Basic authentication:

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)"

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.

echo "${ZITADEL_DOMAIN}/oauth/v2/authorize?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=openid email profile urn:zitadel:iam:user:metadata"

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:

export AUTH_CODE="Y6nWsgR5WB...zUtFqSp5Xw"

Token Request

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:

{
"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:

export ACCESS_TOKEN="jZuRixKQTVecEjKqw...kc3G4"

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.

curl --request GET \
--url "${ZITADEL_DOMAIN}/oidc/v1/userinfo" \
--header "Authorization: Bearer $ACCESS_TOKEN"

The response will look something like this

{
"email":"road.runner@zitadel.com",
"email_verified":true,
"family_name":"Runner",
"given_name":"Road",
"locale":"en",
"name":"Road Runner",
"preferred_username":"road.runner@...asd.zitadel.cloud",
"sub":"166.....729",
"updated_at":1655467738,
"urn:zitadel:iam:user:metadata":{
"ContractNumber":"MTIzNA",
}
}

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)

Check "User Info inside ID Token" in the configuration of your application.

Now request a new token from ZITADEL.

The result will give you something like:

{
"access_token":"jZuRixKQTVecEjKqw...kc3G4",
"token_type":"Bearer",
"expires_in":43199,
"id_token":"ey...Ww"
}

Grab the id_token and inspect the contents of the token at jwt.io. You should get the same info in the ID token as when requested from the user endpoint.