diff --git a/docs/docs/examples/imports/_app_jwt.mdx b/docs/docs/examples/imports/_app_jwt.mdx new file mode 100644 index 0000000000..c5a3c4a7cd --- /dev/null +++ b/docs/docs/examples/imports/_app_jwt.mdx @@ -0,0 +1,53 @@ +1. Go to your Project and click on the **New** button as shown below. + +![Register the API](/img/examples/secure-api/app-jwt/1.png) + +2. Give a name to your application (Test API is the name given below) and select type **API**. + +![Register the API](/img/examples/secure-api/app-jwt/2.png) + +3. Select **JWT** as the authentication method and click **Continue**. + +![Register the API](/img/examples/secure-api/app-jwt/3.png) + +4. Now review your configuration and click **Create**. + +![Register the API](/img/examples/secure-api/app-jwt/4.png) + +5. You will now see the API’s **Client ID**. You will not see a Client Secret because we are using a private JWT key. + +![Register the API](/img/examples/secure-api/app-jwt/5.png) + +6. Next, we must create the key pairs. Click on **New**. + +![Register the API](/img/examples/secure-api/app-jwt/6.png) + +7. Select **JSON** as the type of key. You can also set an expiration time for the key or leave it empty. Click on **Add**. + +![Register the API](/img/examples/secure-api/app-jwt/7.png) + +8. Download the created key by clicking the **Download** button and then click **Close**. + +![Register the API](/img/examples/secure-api/app-jwt/8.png) + +9. The key will be downloaded. + +![Register the API](/img/examples/secure-api/app-jwt/9.png) + +10. When you click on URLs on the left, you will see the relevant OIDC URLs. Note down the **issuer** URL, **token_endpoint** and **introspection_endpoint**. + +![Register the API](/img/examples/secure-api/app-jwt/10.png) + +11. The key that you downloaded will be of the following format. +``` +{ + "type":"application", + "keyId":"", + "key":"-----BEGIN RSA PRIVATE KEY-----\\n-----END RSA PRIVATE KEY-----\n", + "appId":"", + "clientId":"" +} +``` +12. Also note down the **Resource ID** of your project. + +![Register the API](/img/examples/secure-api/app-jwt/11.png) \ No newline at end of file diff --git a/docs/docs/examples/imports/_serviceuser_jwt.mdx b/docs/docs/examples/imports/_serviceuser_jwt.mdx new file mode 100644 index 0000000000..fce665d1be --- /dev/null +++ b/docs/docs/examples/imports/_serviceuser_jwt.mdx @@ -0,0 +1,49 @@ + +1. Go to the **Users** tab in your organization as shown below and click on the **Service Users** tab. + +![Register the API](/img/examples/secure-api/service-user-jwt/1.png) + +2. To add a service user, click on the **New** button. + +![Register the API](/img/examples/secure-api/service-user-jwt/2.png) + + +3. Next, add the details of the service user and select either **Bearer** or **JWT** for **Access Token Type** and click on **Create**. For this example, we will select **JWT**. + +![Register the API](/img/examples/secure-api/service-user-jwt/3.png) + + +4. Now you will see the saved details. + +![Register the API](/img/examples/secure-api/service-user-jwt/4.png) + + +5. Next, we need to generate a private-public key pair in ZITADEL and you must get the private key to sign your JWT. Go to **Keys** and click on **New**. + +![Register the API](/img/examples/secure-api/service-user-jwt/5.png) + + +6. Select type **JSON** and click **Add**. + +![Register the API](/img/examples/secure-api/service-user-jwt/6.png) + +7. Download the key by clicking **Download**. After the download, click **Close**. + +![Register the API](/img/examples/secure-api/service-user-jwt/7.png) + + +8. You will see the following screen afterwards. + +![Register the API](/img/examples/secure-api/service-user-jwt/8.png) + + +9. The downloaded key will be of the following format: + +``` +{ + "type":"serviceaccount", + "keyId":"", + "key":"-----BEGIN RSA PRIVATE KEY-----\n\n-----END RSA PRIVATE KEY-----\n", + "userId":"" +} +``` \ No newline at end of file diff --git a/docs/docs/examples/imports/_serviceuser_role.mdx b/docs/docs/examples/imports/_serviceuser_role.mdx new file mode 100644 index 0000000000..67415682c4 --- /dev/null +++ b/docs/docs/examples/imports/_serviceuser_role.mdx @@ -0,0 +1,36 @@ +In order to access this route, you must create the role `read:messages` in your ZITADEL project and also create an authorization for the service user you created by adding the role to the user. Follow these steps to do so: + +1. Go to your project and select **Roles**. Click **New**. + +![Register the API](/img/examples/secure-api/service-user-jwt/scopes/1.png) + +2. Add the `read:messages` role as shown below and click **Save**. + +![Register the API](/img/examples/secure-api/service-user-jwt/scopes/2.png) + +3. You will see the created role listed. + +![Register the API](/img/examples/secure-api/service-user-jwt/scopes/3.png) + +4. To assign this role to a user, click on **Authorizations**. + +![Register the API](/img/examples/secure-api/service-user-jwt/scopes/4.png) + +5. Select the user you want to assign the role to. + +![Register the API](/img/examples/secure-api/service-user-jwt/scopes/5.png) + +6. Select the project where this authorization is applicable. + +![Register the API](/img/examples/secure-api/service-user-jwt/scopes/6.png) +7. Click **Continue**. + +![Register the API](/img/examples/secure-api/service-user-jwt/scopes/7.png) + +8. Select the role **read:messages** and click **Save**. + +![Register the API](/img/examples/secure-api/service-user-jwt/scopes/8.png) + +9. You will now see the your service user has been assigned the role **read:messages**. + +![Register the API](/img/examples/secure-api/service-user-jwt/scopes/9.png) \ No newline at end of file diff --git a/docs/docs/examples/imports/_setup_django.mdx b/docs/docs/examples/imports/_setup_django.mdx new file mode 100644 index 0000000000..2de0cb063d --- /dev/null +++ b/docs/docs/examples/imports/_setup_django.mdx @@ -0,0 +1,9 @@ +To install Django: +```bash +python -m pip install Django +``` + +Then in your folder of choice call the following command to create a Django base: +```bash +django-admin startproject mysite . +``` diff --git a/docs/docs/examples/imports/_setup_dotenv.mdx b/docs/docs/examples/imports/_setup_dotenv.mdx new file mode 100644 index 0000000000..1b4194831a --- /dev/null +++ b/docs/docs/examples/imports/_setup_dotenv.mdx @@ -0,0 +1,5 @@ +As we use local environmental variables please install dotenv: + +```bash +python -m pip install python-dotenv +``` diff --git a/docs/docs/examples/imports/_setup_python.mdx b/docs/docs/examples/imports/_setup_python.mdx new file mode 100644 index 0000000000..64f55286a7 --- /dev/null +++ b/docs/docs/examples/imports/_setup_python.mdx @@ -0,0 +1 @@ +You have to install Python as described in [their documentation](https://wiki.python.org/moin/BeginnersGuide/Download). \ No newline at end of file diff --git a/docs/docs/examples/introduction.mdx b/docs/docs/examples/introduction.mdx index 689b9c812a..c0191494b6 100644 --- a/docs/docs/examples/introduction.mdx +++ b/docs/docs/examples/introduction.mdx @@ -117,11 +117,20 @@ Our examples cover a range of programming languages and frameworks, so no matter python - Python3 Flask Web + Python Flask Web + + + python + + Python Django Web + + Guide + + dotnet @@ -161,6 +170,15 @@ Our examples cover a range of programming languages and frameworks, so no matter Guide + + + phyton + + Python Django + + Guide + + dotnet diff --git a/docs/docs/examples/login/django.mdx b/docs/docs/examples/login/django.mdx new file mode 100644 index 0000000000..351d45f7b6 --- /dev/null +++ b/docs/docs/examples/login/django.mdx @@ -0,0 +1,241 @@ +--- +title: ZITADEL with Django Python +sidebar_label: Django +--- + +import SetupPython from '../imports/_setup_python.mdx'; +import SetupDjango from '../imports/_setup_django.mdx'; +import SetupDotenv from '../imports/_setup_dotenv.mdx'; + +This integration guide demonstrates the recommended way to incorporate ZITADEL into your Django Python application. +It explains how to enable user login in your application and how to incorporate the ZITADEL users into the existing AuthenticationBackend. + +By the end of this guide, your application will have login functionality with basic role mapping, admin console and polls as described in the Django guide. + +:::info +This documentation references our [example](https://github.com/zitadel/example-django-python-oidc) on GitHub. +::: + +## ZITADEL setup + +Before we can start building our application, we have to do a few configuration steps in ZITADEL Console. + +### Project roles + +The Example expects [user roles](guides/integrate/retrieve-user-roles) to be returned after login. +This example expects 3 different roles: +- `admin`: superuser with permissions to use the admin console +- `staff`: user with permissions to see results of the polls +- `user`: normal user with permission to vote on the existing polls + +In your project settings make sure the "Assert Roles On Authentication" is enabled. + +![Project settings in console](/img/django/project-settings.png) + +In the project Role tab, add 3 special roles: + +- `admin` +- `staff` +- `user` + +If none of the roles is provided as a user, the user in Django will not be created. + +![Project roles in console](/img/django/project-roles.png) + +Finally, we can assign the roles to users in the project's authorizations tab. + +![Project authorizations in console](/img/django/project-authorizations.png) + +### Set up application and obtain secrets + +Next you will need to provide some information about your app. + +In your Project, add a new application at the top of the page. +Select Web application type and continue. +We use [Authorization Code](/apis/openidoauth/grant-types#authorization-code) for our Django application. + +![Create app in console](/img/django/app-create.png) + +Select `CODE` in the next step. This makes sure you still get a secret. Note that the secret never gets exposed on the browser and is therefore kept in a confidential environment. Safe the generated secret for later use. + +![Configure app authentication method in console](/img/django/app-auth-method.png) + +With the Redirect URIs field, you tell ZITADEL where it is allowed to redirect users to after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI. + +For the example application we are writing use: + +- `http://localhost:8000/oidc/callback/` as Redirect URI +- `http://localhost:8000/oidc/logout/` as post-logout URI. + +![Configure app redirects console](/img/django/app-redirects.png) + +After the final step you are presented with a client ID and secret. +Copy and paste them to a safe location for later use by the application. +The secret will not be displayed again, but you can regenerate one if you loose it. + +## Setup new Django application + +### Setup Python + + + +### Install dependencies + +For this example we need the following dependencies: +- `django`: to create an API with django +- `python-dotenv`: to use environment variables in the configuration +- `mozilla-django-oidc`: client-side OIDC functionality + +For the dependencies we need a requirements.txt-file with the following content: + +```python reference +https://github.com/zitadel/example-python-django-oidc/blob/main/requirements.txt +``` + +Then install all dependencies with: +```bash +python -m pip install -U requirements.txt +``` + +The used base is the "Writing your first Django app" from the Django documentation under [https://docs.djangoproject.com/en/5.0/intro/](https://docs.djangoproject.com/en/5.0/intro/), +which has documented additional parts in to use [mozilla-django-oidc](https://github.com/mozilla/mozilla-django-oidc) to integrate ZITADEL as AuthenticationBackend. + +:::info +Skip this step if you are connecting ZITADEL to an existing application. +::: + +## Define the Django app + +### Create the settings.py to include mozilla-django-oidc + +To use the mozilla-django-oidc as AuthenticationBackend, there are several things to add to the settings.py, as described in the [documentation "Add settings to settings.py"](https://mozilla-django-oidc.readthedocs.io/en/stable/installation.html#add-settings-to-settings-py): + +Add INSTALLED_APPS: + +```python +INSTALLED_APPS = [ + ... + "mozilla_django_oidc", # Load after auth + ... +] +``` + +Add MIDDLEWARE: + +```python +MIDDLEWARE = [ + #... + "mozilla_django_oidc.middleware.SessionRefresh", +] +``` + +Add AUTHENTICATION_BACKENDS: + +```python +AUTHENTICATION_BACKENDS = ( + "mysite.backend.PermissionBackend", +) +``` + +Add configuration: + +```python reference +https://github.com/zitadel/example-python-django-oidc/blob/main/mysite/settings.py#L130-L174 +``` + +and create a ".env"-file in the root folder with the configuration: + +```bash +ZITADEL_PROJECT = "ID of the project you created the application in ZITADEL" +OIDC_RP_CLIENT_ID = "ClientID provided by the created application in ZITADEL" +OIDC_RP_CLIENT_SECRET = "ClientSecret provided by the created application in ZITADEL" +OIDC_OP_BASE_URL = "Base URL to the ZITADEL instance" +``` + +which should then look something like this: + +```bash +ZITADEL_PROJECT = "249703732336418457" +OIDC_RP_CLIENT_ID = "249703852243222581@python" +OIDC_RP_CLIENT_SECRET = "Zy3OOHaMBTj2sfamW77Vak5BeQ3nEpOf7suPKTnJKaScMh0lPJqUeDOZmgL3bds0" +OIDC_OP_BASE_URL = "https://example.zitadel.cloud" +``` + +### AuthenticationBackend definition + +To create and update the users regarding the roles given in the authentications in ZITADEL a Subclass of OIDCAuthenticationBackend has to be created: + +```python reference +https://github.com/zitadel/example-python-django-oidc/blob/main/mysite/backend.py +``` + +Which handles the users differently depending on if there are roles associated to: +- `admin` -> superuser +- `staff` -> staff +- `user` -> user +- `no role` -> no user gets created + +### URLs + +To handle the callback and logout the urls have to be added to the urls.py: +```python +urlpatterns = [ + #... + path("oidc/", include("mozilla_django_oidc.urls")), +] +``` + +So it should like something like this: +```python reference +https://github.com/zitadel/example-python-django-oidc/blob/main/mysite/urls.py#L21-L28 +``` + +## Configure and run the application + +:::warning +Never store and commit secrets in the ".env" or settings.py file +::: + +### Authentication and authorization + +To check the authentication and authorization the views in the polls application are extended with decorators: + +```python reference +https://github.com/zitadel/example-python-django-oidc/blob/main/mysite/views.py +``` + +- `@method_decorator(login_required, name="dispatch")`: means that the user has to be logged in Django, which only happens if you have one of the 3 roles("admin", "staff" or "user") +- `@method_decorator(staff_member_required, name="dispatch")`: means you have to have at least a staff user ("admin" or "staff") +- `/admin/`: all admin sides are only accessible if you have a superuser with the role "admin" + +:::info +Additional permission checks could be done with "permission_required" from "django.contrib.auth.decorators" also described in the [Django documentation](https://docs.djangoproject.com/en/5.0/topics/auth/customizing/#custom-permissions). +::: + +### DB + +Create and run migrations: + +```bash +python manage.py migrate +``` + +### Run + +You can use a local Django server to test the application. + +```bash +python manage.py runserver +``` + +Visit http://localhost:8000/polls or http://localhost:8000/admin and click around. + +## Completion + +Congratulations! You have successfully integrated your Python Django application with ZITADEL! + +If you get stuck, consider checking out our [example](https://github.com/zitadel/example-python-django-oidc) application. This application includes all the functionalities mentioned in this quick-start. You can start by cloning the repository and defining the settings in the settings.py. If you face issues, contact us or raise an issue on [GitHub](https://github.com/zitadel/example-python-django-oidc/issues). + +### What's next? + +Now that you have enabled authentication, it's time for you to add more authorizations to your application using ZITADEL APIs. To do this, you can refer to the [docs](/apis/introduction) or check out the ZITADEL Console code on [GitHub](https://github.com/zitadel/zitadel) which uses gRPC and OpenAPI to access data. diff --git a/docs/docs/examples/secure-api/django.mdx b/docs/docs/examples/secure-api/django.mdx new file mode 100644 index 0000000000..215f3a8e7a --- /dev/null +++ b/docs/docs/examples/secure-api/django.mdx @@ -0,0 +1,166 @@ +--- +title: ZITADEL with Django Python +sidebar_label: Django +--- + +import AppJWT from '../imports/_app_jwt.mdx'; +import ServiceuserJWT from '../imports/_serviceuser_jwt.mdx'; +import ServiceuserRole from '../imports/_serviceuser_role.mdx'; +import SetupPython from '../imports/_setup_python.mdx'; + +This integration guide demonstrates the recommended way to incorporate ZITADEL into your Django Python application. +It explains how to check the token validity in the API and how to check for permissions. + +By the end of this guide, your application will have three different endpoint which are public, private(valid token) and private-scoped(valid token with specific role). + +:::info +This documentation references our [example](https://github.com/zitadel/example-django-python-oauth) on GitHub. +::: + +## ZITADEL setup + +Before we can start building our application, we have to do a few configuration steps in ZITADEL Console. + +### Create application + + + +### Create Serviceuser + + + +### Give Serviceuser an authorization + + + +### Prerequisites + +At the end you should have the following for the API: +- Issuer, something like `https://example.zitadel.cloud` or `http://localhost:8080` +- Introspection URL, something like `https://example.zitadel.cloud/oauth/v2/introspect` +- Token URL, something like `https://example.zitadel.cloud/oauth/v2/token` +- `.json`-key-file for the API, from the application +- ID of the project + +And the following from the Serviceuser: +- `.json`-key-file from the serviceuser + +## Setup new Django application + +### Setup Python + + + +### Install dependencies + +For this example we need the following dependencies: +- `django`: to create an API with django +- `python-dotenv`: to use environment variables in the configuration +- `authlib`: client-side OAuth functionality +- `requests`: HTTP requests for the introspection + + +For the dependencies we need a requirements.txt-file with the following content: + +```python reference +https://github.com/zitadel/example-python-django-oauth/blob/main/requirements.txt +``` + +Then install all dependencies with: +```bash +python -m pip install -U requirements.txt +``` + +Then in your folder of choice, call the following command to create a Django base: +```bash +django-admin startproject myapi . +``` + +## Define the Django API + +### Add to the settings.py to include ZITADEL info + +There is info needed for the introspection calls, which we put into the settings.py: + +```python reference +https://github.com/zitadel/example-python-django-oauth/blob/main/myapi/settings.py#L125-L133 +``` + +and create a ".env"-file in the root folder with the configuration as an example: +```bash +ZITADEL_INTROSPECTION_URL = 'URL to the introspection endpoint to verify the provided token' +ZITADEL_DOMAIN = 'Domain used as audience in the token verification' +API_PRIVATE_KEY_FILE_PATH = 'Path to the key.json created in ZITADEL' +``` + +I should look something like this: + +```bash +ZITADEL_INTROSPECTION_URL = 'https://example.zitadel.cloud/oauth/v2/introspect' +ZITADEL_DOMAIN = 'https://example.zitadel.cloud' +API_PRIVATE_KEY_FILE_PATH = '/tmp/example/250719519163548112.json' +``` + +### Validator definition + +To validate the tokens, we need a validator which can be called in the event of API-calls. + +validator.py: + +```python reference +https://github.com/zitadel/example-python-django-oauth/blob/main/myapi/validator.py +``` + +### Requests and URLs + +We define 3 different endpoints which differ in terms of requirements. +views.py: + +```python reference +https://github.com/zitadel/example-python-django-oauth/blob/main/myapi/views.py +``` + +To handle endpoints the urls have to be added to the urls.py: + +```python reference +https://github.com/zitadel/example-python-django-oauth/blob/main/myapi/urls.py +``` + +### DB + +Create and run migrations: + +```bash +python manage.py migrate +``` + +### Run + +You can use a local Django server to test the application. + +```bash +python manage.py runserver +``` + +### Call the API + +To call the API you need an access token, which is then verified by ZITADEL. +Please follow [this guide here](https://zitadel.com/docs/guides/integrate/private-key-jwt#get-an-access-token), ignoring the first step as we already have the `.json`-key-file from the serviceaccount. + +Optionally set the token as an environment variable: +``` +export TOKEN='MtjHodGy4zxKylDOhg6kW90WeEQs2q...' +``` + +With the access token, you can then do the following calls: +``` +curl -H "Authorization: Bearer $TOKEN" -X GET http://localhost:8000/api/public +curl -H "Authorization: Bearer $TOKEN" -X GET http://localhost:8000/api/private +curl -H "Authorization: Bearer $TOKEN" -X GET http://localhost:8000/api/private-scoped +``` + +## Completion + +Congratulations! You have successfully integrated your Django API with ZITADEL! + +If you get stuck, consider checking out our [example](https://github.com/zitadel/example-python-django-oauth) application. This application includes all the functionalities mentioned in this quick-start. You can start by cloning the repository and defining the settings in the settings.py. If you face issues, contact us or raise an issue on [GitHub](https://github.com/zitadel/example-python-django-oauth/issues). diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index da5a601136..89dd422f0e 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -178,7 +178,7 @@ module.exports = { selector: "div#", }, prism: { - additionalLanguages: ["csharp", "dart", "groovy", "regex", "java", "php"], + additionalLanguages: ["csharp", "dart", "groovy", "regex", "java", "php", "python"], }, colorMode: { defaultMode: "dark", diff --git a/docs/static/img/django/app-auth-method.png b/docs/static/img/django/app-auth-method.png new file mode 100644 index 0000000000..481066cdca Binary files /dev/null and b/docs/static/img/django/app-auth-method.png differ diff --git a/docs/static/img/django/app-create.png b/docs/static/img/django/app-create.png new file mode 100644 index 0000000000..580eaa9187 Binary files /dev/null and b/docs/static/img/django/app-create.png differ diff --git a/docs/static/img/django/app-redirects.png b/docs/static/img/django/app-redirects.png new file mode 100644 index 0000000000..d0ab8df906 Binary files /dev/null and b/docs/static/img/django/app-redirects.png differ diff --git a/docs/static/img/django/project-authorizations.png b/docs/static/img/django/project-authorizations.png new file mode 100644 index 0000000000..7e702736dd Binary files /dev/null and b/docs/static/img/django/project-authorizations.png differ diff --git a/docs/static/img/django/project-roles.png b/docs/static/img/django/project-roles.png new file mode 100644 index 0000000000..3606c08e9e Binary files /dev/null and b/docs/static/img/django/project-roles.png differ diff --git a/docs/static/img/django/project-settings.png b/docs/static/img/django/project-settings.png new file mode 100644 index 0000000000..fd220a0414 Binary files /dev/null and b/docs/static/img/django/project-settings.png differ diff --git a/docs/static/img/examples/secure-api/app-jwt/1.png b/docs/static/img/examples/secure-api/app-jwt/1.png new file mode 100644 index 0000000000..1025eb869e Binary files /dev/null and b/docs/static/img/examples/secure-api/app-jwt/1.png differ diff --git a/docs/static/img/examples/secure-api/app-jwt/10.png b/docs/static/img/examples/secure-api/app-jwt/10.png new file mode 100644 index 0000000000..05c58384b1 Binary files /dev/null and b/docs/static/img/examples/secure-api/app-jwt/10.png differ diff --git a/docs/static/img/examples/secure-api/app-jwt/11.png b/docs/static/img/examples/secure-api/app-jwt/11.png new file mode 100644 index 0000000000..c3b9843832 Binary files /dev/null and b/docs/static/img/examples/secure-api/app-jwt/11.png differ diff --git a/docs/static/img/examples/secure-api/app-jwt/2.png b/docs/static/img/examples/secure-api/app-jwt/2.png new file mode 100644 index 0000000000..1bb5927636 Binary files /dev/null and b/docs/static/img/examples/secure-api/app-jwt/2.png differ diff --git a/docs/static/img/examples/secure-api/app-jwt/3.png b/docs/static/img/examples/secure-api/app-jwt/3.png new file mode 100644 index 0000000000..d4deeb6e9d Binary files /dev/null and b/docs/static/img/examples/secure-api/app-jwt/3.png differ diff --git a/docs/static/img/examples/secure-api/app-jwt/4.png b/docs/static/img/examples/secure-api/app-jwt/4.png new file mode 100644 index 0000000000..7063c251ea Binary files /dev/null and b/docs/static/img/examples/secure-api/app-jwt/4.png differ diff --git a/docs/static/img/examples/secure-api/app-jwt/5.png b/docs/static/img/examples/secure-api/app-jwt/5.png new file mode 100644 index 0000000000..9f5bddb7db Binary files /dev/null and b/docs/static/img/examples/secure-api/app-jwt/5.png differ diff --git a/docs/static/img/examples/secure-api/app-jwt/6.png b/docs/static/img/examples/secure-api/app-jwt/6.png new file mode 100644 index 0000000000..d213eaee94 Binary files /dev/null and b/docs/static/img/examples/secure-api/app-jwt/6.png differ diff --git a/docs/static/img/examples/secure-api/app-jwt/7.png b/docs/static/img/examples/secure-api/app-jwt/7.png new file mode 100644 index 0000000000..d783c92cd7 Binary files /dev/null and b/docs/static/img/examples/secure-api/app-jwt/7.png differ diff --git a/docs/static/img/examples/secure-api/app-jwt/8.png b/docs/static/img/examples/secure-api/app-jwt/8.png new file mode 100644 index 0000000000..47299c0920 Binary files /dev/null and b/docs/static/img/examples/secure-api/app-jwt/8.png differ diff --git a/docs/static/img/examples/secure-api/app-jwt/9.png b/docs/static/img/examples/secure-api/app-jwt/9.png new file mode 100644 index 0000000000..e20a664493 Binary files /dev/null and b/docs/static/img/examples/secure-api/app-jwt/9.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/1.png b/docs/static/img/examples/secure-api/service-user-jwt/1.png new file mode 100644 index 0000000000..b0e0172213 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/1.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/2.png b/docs/static/img/examples/secure-api/service-user-jwt/2.png new file mode 100644 index 0000000000..85696c011d Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/2.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/3.png b/docs/static/img/examples/secure-api/service-user-jwt/3.png new file mode 100644 index 0000000000..1931398d15 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/3.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/4.png b/docs/static/img/examples/secure-api/service-user-jwt/4.png new file mode 100644 index 0000000000..bd5db4ad49 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/4.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/5.png b/docs/static/img/examples/secure-api/service-user-jwt/5.png new file mode 100644 index 0000000000..f64fb35f49 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/5.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/6.png b/docs/static/img/examples/secure-api/service-user-jwt/6.png new file mode 100644 index 0000000000..31da888036 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/6.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/7.png b/docs/static/img/examples/secure-api/service-user-jwt/7.png new file mode 100644 index 0000000000..bd4ebb0a07 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/7.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/8.png b/docs/static/img/examples/secure-api/service-user-jwt/8.png new file mode 100644 index 0000000000..bceac10342 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/8.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/9.png b/docs/static/img/examples/secure-api/service-user-jwt/9.png new file mode 100644 index 0000000000..e201d686d7 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/9.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/scopes/1.png b/docs/static/img/examples/secure-api/service-user-jwt/scopes/1.png new file mode 100644 index 0000000000..d0cd03e5d9 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/scopes/1.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/scopes/2.png b/docs/static/img/examples/secure-api/service-user-jwt/scopes/2.png new file mode 100644 index 0000000000..68895310fc Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/scopes/2.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/scopes/3.png b/docs/static/img/examples/secure-api/service-user-jwt/scopes/3.png new file mode 100644 index 0000000000..bd6821807b Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/scopes/3.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/scopes/4.png b/docs/static/img/examples/secure-api/service-user-jwt/scopes/4.png new file mode 100644 index 0000000000..77df97174f Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/scopes/4.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/scopes/5.png b/docs/static/img/examples/secure-api/service-user-jwt/scopes/5.png new file mode 100644 index 0000000000..9d67e1739e Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/scopes/5.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/scopes/6.png b/docs/static/img/examples/secure-api/service-user-jwt/scopes/6.png new file mode 100644 index 0000000000..983f19cee1 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/scopes/6.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/scopes/7.png b/docs/static/img/examples/secure-api/service-user-jwt/scopes/7.png new file mode 100644 index 0000000000..2516e8b041 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/scopes/7.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/scopes/8.png b/docs/static/img/examples/secure-api/service-user-jwt/scopes/8.png new file mode 100644 index 0000000000..1b110124d4 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/scopes/8.png differ diff --git a/docs/static/img/examples/secure-api/service-user-jwt/scopes/9.png b/docs/static/img/examples/secure-api/service-user-jwt/scopes/9.png new file mode 100644 index 0000000000..deef3052a4 Binary files /dev/null and b/docs/static/img/examples/secure-api/service-user-jwt/scopes/9.png differ