diff --git a/docs/docs/guides/customization/user-metadata.md b/docs/docs/guides/customization/user-metadata.md new file mode 100644 index 0000000000..15b936c5fe --- /dev/null +++ b/docs/docs/guides/customization/user-metadata.md @@ -0,0 +1,228 @@ +--- +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. + +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](https://docs.zitadel.com/docs/guides/basics/applications#web) +- 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](https://docs.zitadel.com/docs/manuals/user-profile#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. + +```bash +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](https://docs.zitadel.com/docs/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)" +``` + + + + + +```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`. + + + + + +```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`. + + + + + +You need to create a string as described [here](https://docs.zitadel.com/docs/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`. + + + + +### 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](https://docs.zitadel.com/docs/apis/openidoauth/scopes#reserved-scopes). + + + + + +```bash +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" +``` + + + + + +```zsh +open "${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" +``` + + + + +```bash +wslview "${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: + +```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" +``` + +### 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. + +```bash +curl --request GET \ + --url "${ZITADEL_DOMAIN}/oidc/v1/userinfo" \ + --header "Authorization: Bearer $ACCESS_TOKEN" +``` + +The response will look something like this + +```json +{ + "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, + //highlight-start + "urn:zitadel:iam:user:metadata":{ + "ContractNumber":"MTIzNA", + } + //highlight-end + } +``` + +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. + +![](/img/console_projects_application_token_settings.png) + +Now request a new token from ZITADEL. + +The result will give you something like: + +```json +{ + "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](https://jwt.io/). You should get the same info in the ID token as when requested from the user endpoint. \ No newline at end of file diff --git a/docs/sidebars.js b/docs/sidebars.js index 825b4861a4..1ed92edd40 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -109,7 +109,8 @@ module.exports = { items: [ "guides/customization/branding", "guides/customization/texts", - "guides/customization/behavior" + "guides/customization/behavior", + "guides/customization/user-metadata" ], }, { diff --git a/docs/static/img/console_projects_application_token_settings.png b/docs/static/img/console_projects_application_token_settings.png new file mode 100644 index 0000000000..e7a4d12b21 Binary files /dev/null and b/docs/static/img/console_projects_application_token_settings.png differ